Не могу сравнить сотые доли числа

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Ответить
Dr_Grizzly
Сообщения: 407
Зарегистрирован: 13 сен 2004, 12:05
Откуда: Курган
Контактная информация:

Всем привет! Такая ситуация, в таблице два текстовых поля, sum1 и sum2, в коде делаю следующее:

Код: Выделить всё

....
var
s:Real;
begin
....
s:=ABS(StrToFloat(Table1Sum1.text)-StrToFloat(Table1.sum2.text));

If s<>0.01 then
 ShowMessage('аааа');
...
end;
В отладчике я ставлю точку останова и смотрю что переменная s имеет значение 0.01
и она все равно выдает сообщение 'aaaa'

Второй вариант:

Код: Выделить всё

....
var
x,s:Real;
begin
....
x:=0.01;

s:=ABS(StrToFloat(Table1Sum1.text)-StrToFloat(Table1.sum2.text));

If s<>x then
 ShowMessage('аааа');
...
end;

Картина повторилась

Третий вариант

Код: Выделить всё

....
var
x,s:Real;
begin
....
x:=0.01;

s:=ABS(StrToFloat(Table1Sum1.text)-StrToFloat(Table1.sum2.text));

If FloatToStr(s)<>FloatToStr(x) then
 ShowMessage('аааа');
...
end;

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

Мне нужно что сообщение не выдавало.
Чем проще - тем оригинальней, а значит гениально, т.к. все гениальное - просто! ;) Да! Кстати! Ctrl+V реально вставляет!!! ХDD
Аватара пользователя
somewhere
Сообщения: 1858
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

Тип Real имеет размер 6 байт, числовой процессор работать с такими данными не умеет. Для вещественных чисел допустимые размеры 4,8 и 10 байт (single, double и Extended) соответственно. При присваивании переменной Real значений, компилятор выделяет переменной не 6, а 8 байт что эквивалентно типу Double. Число 0.1 мифическое в двоичном понимании и может быть представлено в виде бесконечной двоичной последовательности. При расчетах даже если у вас получилось точно 0.1, последний бит числа в сопроцессоре может отличаться. Такое может произойти при оперировании с "бесконечно" представимым числами, либо числами разных порядков. Механизм работы с такими числами сопроцессора подробно описан в документации Intel. Исходя из этого операции сравнения с такими числами могут давать как верный, так и неверный результат. Как вариант решения можно предложить увеличить разрядность переменных до 10 байт, это увеличит ваши шансы на верное сравнение, но полной гарантии не даст. Попробуйте выберите другое число, например 0.1015625, либо то, которое представимо конечным числом битов.
It's a long way to the top if you wanna rock'n'roll
Dr_Grizzly
Сообщения: 407
Зарегистрирован: 13 сен 2004, 12:05
Откуда: Курган
Контактная информация:

Обалдеть!!! Вот это проблема! ))) А если переменную объявить как double? Поможет? А лучше наверное FloatToCurr???
Чем проще - тем оригинальней, а значит гениально, т.к. все гениальное - просто! ;) Да! Кстати! Ctrl+V реально вставляет!!! ХDD
Аватара пользователя
Игорь Акопян
Сообщения: 1440
Зарегистрирован: 13 окт 2004, 17:11
Откуда: СПБ
Контактная информация:

читать http://www.delphikingdom.ru/asp/viewite ... alogid=374 , офигевать, далее либо научиться с этим жить, либо менять работу ;)
Изображение
Аватара пользователя
somewhere
Сообщения: 1858
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

Сравнение таких чисел лучше выполнять на примере вхождения в малую "окрестность" числа
It's a long way to the top if you wanna rock'n'roll
chur
Сообщения: 195
Зарегистрирован: 17 фев 2004, 10:44
Откуда: Riga, Latvia

Игорь Акопян, спасибо за ссылку.

Теперь я понял, почему эти плавающие числа мне сразу не понравились :D
MOTOCoder
Сообщения: 548
Зарегистрирован: 14 янв 2008, 20:27
Откуда: Россия, Псков

Игорь Акопян писал(а):читать http://www.delphikingdom.ru/asp/viewite ... alogid=374 , офигевать, далее либо научиться с этим жить, либо менять работу ;)


Мда... Интересно.
Казалось бы - что может быть точнее компьютера? :)
Ни что так не ограничивает фантазию программиста, как компилятор...
Ответить