Помогите! Я тут с ума уже схожу с !=
От: Аноним  
Дата: 30.03.05 14:09
Оценка:
имеем:
double o1
double b1

if (b1 != o1)
{
test << "1 : " << o1 << "," << b1 << endl;
}

В ответ получаем
1 : 125.21,125.21

Преобразование типа не помогает
if ( (int(1000*b1)) != (int(1000*o1)) )


Проблема в том, что с o1 и b1 в программе проводится куча вычислений
все это находится в цикле и выскакивает далеко не сразу,
поэтому я и анализирую именно текстовый файл.

Какие могут быть причины возникновения такого глюка?

Как в диагностических целях вывести значение переменных в тестовый файл, чтобы этот глюк можно было отловить?
Re: Помогите! Я тут с ума уже схожу с !=
От: Анатолий Широков СССР  
Дата: 30.03.05 14:15
Оценка:
А ты сравнивай на равенство с заданной точностью.
Re[2]: Помогите! Я тут с ума уже схожу с !=
От: Аноним  
Дата: 30.03.05 14:16
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>А ты сравнивай на равенство с заданной точностью.


А как это сделать?
Re: Помогите! Я тут с ума уже схожу с !=
От: LuciferMoscow Россия  
Дата: 30.03.05 14:18
Оценка:
Кто же тебя так учил double сравнивать?
a-b < eps, где eps маленькое 1e-8

double на равенство низя. Почему — искать по форуму.
Re[3]: Помогите! Я тут с ума уже схожу с !=
От: alseides  
Дата: 30.03.05 14:18
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>А ты сравнивай на равенство с заданной точностью.


А>А как это сделать?


if(abs(a-b)<0.000001)
Re[4]: Помогите! Я тут с ума уже схожу с !=
От: Анатолий Широков СССР  
Дата: 30.03.05 14:20
Оценка:
if(fabs(a-b)<0.000001)
Re[5]: Помогите! Я тут с ума уже схожу с !=
От: Аноним  
Дата: 30.03.05 14:26
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:


АШ>
АШ>if(fabs(a-b)<0.000001)
АШ>


Это я понимаю.
А почему такая фигня может происходить?
Что же теперь при каждой проверке на равенсво это использовать?
Re[2]: Помогите! Я тут с ума уже схожу с !=
От: ssm Россия  
Дата: 30.03.05 14:31
Оценка: :)))
Здравствуйте, LuciferMoscow, Вы писали:

LM>Кто же тебя так учил double сравнивать?

LM>a-b < eps, где eps маленькое 1e-8

а тебя хто так учил?
по модулю, батенька, по модулю...
Re[6]: Помогите! Я тут с ума уже схожу с !=
От: Анатолий Широков СССР  
Дата: 30.03.05 14:34
Оценка:
А>Это я понимаю.
А>А почему такая фигня может происходить?

Проблема в том, что мощность множества вещественных чисел равна бесконечности, поэтому только узкое подмножество вещественных чисел представимо в памяти машины точно.

А>Что же теперь при каждой проверке на равенсво это использовать?


При каждой.
Re[6]: Помогите! Я тут с ума уже схожу с !=
От: Leshi Россия  
Дата: 30.03.05 14:39
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Что же теперь при каждой проверке на равенсво это использовать?

Ну, как вариант, напсать арифметику для чисел с фиксированой точкой и работать с ними (я таким как-то занимался, деньги считал). Там все проще: чего сказал, то и будет =)
... << RSDN@Home 1.1.3 stable >>
Re[3]: Помогите! Я тут с ума уже схожу с !=
От: LuciferMoscow Россия  
Дата: 30.03.05 14:40
Оценка:
Здравствуйте, ssm, Вы писали:

ssm>Здравствуйте, LuciferMoscow, Вы писали:


LM>>Кто же тебя так учил double сравнивать?

LM>>a-b < eps, где eps маленькое 1e-8

ssm>а тебя хто так учил?

ssm>по модулю, батенька, по модулю...
ssm>
ну и на старуху....
Re[7]: Помогите! Я тут с ума уже схожу с !=
От: Аноним  
Дата: 30.03.05 15:02
Оценка:
АШ>Проблема в том, что мощность множества вещественных чисел равна бесконечности, поэтому только узкое подмножество вещественных чисел представимо в памяти машины точно.

О! Я слово мощность в этом контексте не слышал с момент окончания мат. анализа в институте, но помню, что оно значит.
Все это я понимаю.
Я не понимаю, где конкретно возникает (может возникать) ошибка и как это место отловить?


А>>Что же теперь при каждой проверке на равенсво это использовать?


АШ>При каждой.



А если все числа в моей программе будут ограничены по количеству знаков двумя знаками после запятой и умножения/деления я не буду проводить, тогда можно пользоваться ==(!=)?
Re[6]: Помогите! Я тут с ума уже схожу с !=
От: Ash-2 Россия  
Дата: 30.03.05 15:23
Оценка:
Здравствуйте, Аноним, Вы писали:

Я тут
Автор:
Дата: 04.03.05
недавно тоже интересовался этой проблемой.
Re[8]: Помогите! Я тут с ума уже схожу с !=
От: Warturtle  
Дата: 30.03.05 15:28
Оценка: :))
Здравствуйте, Аноним, Вы писали:

АШ>>Проблема в том, что мощность множества вещественных чисел равна бесконечности, поэтому только узкое подмножество вещественных чисел представимо в памяти машины точно.


А>О! Я слово мощность в этом контексте не слышал с момент окончания мат. анализа в институте, но помню, что оно значит.


Можно было сказать проще: "вещественных чисел бесконечно много", но с "мощностью" звучит заметно авторитетнее=))
Re[8]: Помогите! Я тут с ума уже схожу с !=
От: Анатолий Широков СССР  
Дата: 30.03.05 15:34
Оценка:
А>О! Я слово мощность в этом контексте не слышал с момент окончания мат. анализа в институте, но помню, что оно значит.
А>Все это я понимаю.
А>Я не понимаю, где конкретно возникает (может возникать) ошибка и как это место отловить?

Конечно, в результате вычислений.

А>>>Что же теперь при каждой проверке на равенсво это использовать?


АШ>>При каждой.


А>А если все числа в моей программе будут ограничены по количеству знаков двумя знаками после запятой и умножения/деления я не буду проводить, тогда можно пользоваться ==(!=)?


Здесь важно не два знака после запятой, а важно другое — могут ли они быть представлены точно числами с плавающей запятой. Если могут, то сравнивайте.
Re[8]: Помогите! Я тут с ума уже схожу с !=
От: Кодт Россия  
Дата: 30.03.05 17:35
Оценка: 29 (3) +1
Здравствуйте, Аноним, Вы писали:

А>А если все числа в моей программе будут ограничены по количеству знаков двумя знаками после запятой и умножения/деления я не буду проводить, тогда можно пользоваться ==(!=)?


Двумя знаками в какой системе счисления? Если в десятичной, то это бесперспективняк: конечные десятичные дроби — периодические двоичные.
Конечно, можно каждый результат вычислений сразу округлять — хоть до двух десятичных знаков, хоть до чего угодно. То есть, работать с ещё меньшим подмножеством вещественных чисел, чем double.
Только из-за этого ошибки вычислений будут расти ещё стремительнее.

Ведь откуда возникают неравенства:
Есть две функции над вещественными числами: f(x), g(x), причём известно, что f(x0)==g(x0).
Переходя к числам конечной точности (плавающим или фиксированным — неважно), мы вводим ошибку: X0 = R(x0) = x0+dx.
При этом уже не факт, что f(X0)==g(X0).
(x,f,g — точные значения и функции, X,F,G — вычислимые).

Далее, вычисляя эти функции, мы к этой погрешности добавляем разнообразные ошибки, связанные с конечной разрядной сеткой и конечным временем вычислений. Поскольку формулы f и g разные, то результирущие отклонения от ожидаемого
значения, df = F(X0)-R(f(X0)), dg = G(X0)-R(g(X0)) — будут разными.

Поэтому, F(X0)!=G(X0), хотя f(x0)==g(x0).
Однако, можно оценить погрешность вычислений — то есть, максимальный разброс df и dg.
Если eps = max(|df|+|dg|) на некотором множестве x, то |F(X0)-G(X0)| <= eps.

Ну и, кроме прочего, есть вычисления, дающие бОльшие и меньшие ошибки.
Наверное, самый известный пример: суммирование множества чисел с плавающей запятой.
Две основных беды — это ошибки денормализации и нормализации. На плохом наборе (сначала складываем очень большие числа, потом очень маленькие) это может привести к изумительным результатам:
1 + 0.00000000000001{*10000000000000} == 1.
Суммирование по Хаффману (вынимаем два самых маленьких по модулю числа, складываем, возвращаем результат в набор) минимизирует эту засаду.
Перекуём баги на фичи!
Re[9]: Помогите! Я тут с ума уже схожу с !=
От: Cyberax Марс  
Дата: 31.03.05 05:26
Оценка: +1
Warturtle пишет:

> АШ>>Проблема в том, что мощность множества вещественных чисел равна

> бесконечности, поэтому только узкое подмножество вещественных чисел
> представимо в памяти машины точно.
> А>О! Я слово мощность в этом контексте не слышал с момент окончания
> мат. анализа в институте, но помню, что оно значит.
> Можно было сказать проще: "вещественных чисел бесконечно много", но с
> "мощностью" звучит заметно авторитетнее=))

Еще авторитетнее: "мощность множества вещественных чисел равна алеф-1"

--
С уважением,
Alex Besogonov (alexy@izh.com)
Posted via RSDN NNTP Server 1.9
Sapienti sat!
Re[9]: Помогите! Я тут с ума уже схожу с !=
От: Аноним  
Дата: 31.03.05 06:16
Оценка:
Спасибо за развернутые ответы.
Все понял!
Re[7]: Помогите! Я тут с ума уже схожу с !=
От: Николай Ганичев Россия  
Дата: 31.03.05 07:07
Оценка: :)
Здравствуйте, Анатолий Широков, Вы писали:

АШ>Проблема в том, что мощность множества вещественных чисел равна бесконечности


Извиняюсь, но множество вещественных чисел континуально. Его мощность — континуум.
... << RSDN@Home 1.1.4 @@subversion >>
Re[5]: Помогите! Я тут с ума уже схожу с !=
От: Андрей Тарасевич Беларусь  
Дата: 31.03.05 07:40
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>
АШ>if(fabs(a-b)<0.000001)
АШ>


В С++ можно

if(abs(a-b)<0.000001)
Best regards,
Андрей Тарасевич
Re[4]: А почему проверки не относительные?
От: Erop Россия  
Дата: 31.03.05 08:04
Оценка: 9 (1) :)
Ошибки double относительные, поэтому казалось бы, иногда стоит сравнивать не с "очень маленькой константой", а смотреть на относительную погрешность.

Разве нет?
Скажем так:

inline bool IsEquDouble( double a, double b, dauble eps = DBL_EPSILON * 10 )
{
    assert( eps > 0 );
    return abs( a - b ) <= eps * max( a, b );
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: А почему проверки не относительные?
От: WoldemaR Россия  
Дата: 31.03.05 09:05
Оценка: -1
Здравствуйте, Erop, Вы писали:

E>Скажем так:

...

Лучше так:
#include <limits>

template <typename t1, typename t2>
bool IsEqual(const t1& v1, const t2& v2)
{
    return ::abs(v1 - v2) <=
        max(std::numeric_limits<t1>::epsilon(),
            std::numeric_limits<t2>::epsilon());
};
Re[8]: Помогите! Я тут с ума уже схожу с !=
От: Warturtle  
Дата: 31.03.05 09:07
Оценка:
Здравствуйте, Николай Ганичев, Вы писали:

НГ>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>Проблема в том, что мощность множества вещественных чисел равна бесконечности


НГ>Извиняюсь, но множество вещественных чисел континуально. Его мощность — континуум.

И что? Оно же от этого конечным не становится "В контексте рассматриваемой проблемы" — это "монопенисуально", т.е. все равно какой "алеф"- нуль, один или больше=)
Re[6]: А почему проверки не относительные?
От: Erop Россия  
Дата: 31.03.05 10:00
Оценка:
Здравствуйте, WoldemaR, Вы писали:

WR>Лучше так:

WR>
WR>#include <limits>

WR>template <typename t1, typename t2>
WR>bool IsEqual(const t1& v1, const t2& v2)
WR>{
WR>    return ::abs(v1 - v2) <=
WR>        max(std::numeric_limits<t1>::epsilon(),
WR>            std::numeric_limits<t2>::epsilon());
WR>};
WR>



Два вопроса:

1. Почему эта проверка относительная?
2. Почему считается, что std::numeric_limits<t2>::epsilon() — это именно та точность, которая нужна?

Уточняю:

1.

два числа 10000000.1 и 10000000.2 почти не отличаются, а 0.100000000001 и 0.200000000001 отличаются примерно в два раза.
Если проверка относительная, то она заметит разницу, а если нет -- то нет


2.

насколько я помню std::numeric_limits<double>::epsilon() -- это самое маленькое double число, которое при добавлении к 1.0 даст результат отличный от 1.0.
В реальных вычислениях ошибки округления больше, так как обычно операций больше одной. Но при этом такая точность обычно бывает избыточной.
Так что нужно задать какой-то уровень относительной точности, или управлять точностью сравнения на равенство в каждом конкретном месте.

Поэтому нужен и третий параметр, и нужно в его значении брать число намного превосходящее эпсилон, а использовать ли для этого шаблоны -- вопрос стиля. Я, например, не очень понимаю, зачем нужен такой шаблон. Какой тип параметра, кроме double есть желание поддержать?
Обычно все вычисления в программе бывают или double или float
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: А почему проверки не относительные?
От: Erop Россия  
Дата: 31.03.05 10:03
Оценка: +2
Тут, кстати, вкралась ошибка

E>inline bool IsEquDouble( double a, double b, dauble eps = DBL_EPSILON * 10 )
E>{
E>    assert( eps > 0 );
E>    return abs( a - b ) <= eps * max( a, b );
E>}
E>



Верно так:
inline bool IsEquDouble( double a, double b, dauble eps = DBL_EPSILON * 10 )
{
    assert( eps > 0 );
    return abs( a - b ) <= eps * max( abs( a ), abs( b ) );
}


Извините.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Помогите! Я тут с ума уже схожу с !=
От: Николай Ганичев Россия  
Дата: 31.03.05 13:22
Оценка:
Здравствуйте, Warturtle, Вы писали:

АШ>>>Проблема в том, что мощность множества вещественных чисел равна бесконечности


НГ>>Извиняюсь, но множество вещественных чисел континуально. Его мощность — континуум.


W>И что? Оно же от этого конечным не становится "В контексте рассматриваемой проблемы" — это "монопенисуально", т.е. все равно какой "алеф"- нуль, один или больше=)


То, что утверждение "мощность множества вещественных чисел равна бесконечности" не верно. И только.
... << RSDN@Home 1.1.4 @@subversion >>
Re[10]: Помогите! Я тут с ума уже схожу с !=
От: Mr. None Россия http://mrnone.blogspot.com
Дата: 01.04.05 06:09
Оценка:
Здравствуйте, Cyberax, Вы писали:


C>Еще авторитетнее: "мощность множества вещественных чисел равна алеф-1"


Вы ещё Борхеса вспомните, с его рассуждениеями о том, что может представлять из себя множество мощности алеф четвёртой степени...
Компьютер сделает всё, что вы ему скажете, но это может сильно отличаться от того, что вы имели в виду.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.