Правильно ли сравнивать два округленных числа с плавающей запятой с помощью оператора ==? - PullRequest
6 голосов
/ 25 октября 2008

Или есть вероятность, что операция не удастся?

Спасибо.

Я выбрал неправильный термин, и я действительно имел в виду округление до 0, а не усечение.

Дело в том, что мне нужно сравнить целую часть двух двойных чисел, и я просто приводю их к int, а затем использую ==, но, как кто-то указал в одном из моих предыдущих вопросов, это может привести к переполнению исключение, если двойное не может вписаться в целое число.

Таким образом, вопрос будет: «Правильно ли использовать оператор == для сравнения двух двойных чисел, которые ранее были округлены до 0, или мне следует придерживаться метода cast to int и перехватить возможное исключение?

Ответы [ 6 ]

12 голосов
/ 25 октября 2008

Вот обновленный сайт , на котором обсуждаются плюсы и минусы нескольких методов сравнения чисел с плавающей запятой. (Вы все еще можете просмотреть старый сайт здесь .)

Я бы выбрал метод "относительная ошибка". Найдите разницу между двумя числами, преобразуйте ее в процент от чисел, и если этот процент достаточно мал, то вы получите равенство.

5 голосов
/ 14 марта 2009

Еще хуже то, что иногда, даже для одного и того же числа, он терпит неудачу. Это связано с тем, что некоторые компиляторы или процессоры будут использовать больше битов точности в регистре процессора, чем в памяти (например, MSVC имеет 3 различных варианта поведения с плавающей точкой). Таким образом, недавно вычисленное значение может не иметь этих усеченных битов и будет выглядеть неравным. НИКОГДА не используйте == на поплавках.

4 голосов
/ 25 октября 2008

Он все еще может потерпеть неудачу из-за обычных проблем с представлением с плавающей запятой. Вместо того, чтобы усекать их, используйте дельту, которая будет представлять эквивалентную точность.

Он может потерпеть неудачу в тех случаях, когда у вас есть два числа с плавающей точкой, которые вы обычно считаете одинаковыми,

+10,19999999

+10,20000001

но когда вы их усекаете, они дают разные результаты.

10,19

10,20

Принимая во внимание, что если бы я использовал дельту 0,001 для сравнения с разницей, я бы увидел, что эти два значения фактически одинаковы.

2 голосов
/ 25 октября 2008

Никогда не правильно использовать == с плавающей точкой.

Что означает "усечение" в контексте с плавающей точкой? Какую конкретную библиотечную функцию вы вызываете? Что в итоге? Что заставляет вас верить, что «усеченные» значения более сопоставимы, чем не усеченные значения?

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

Если, однако, вы конвертируете в целое число, вы можете использовать ==.

1 голос
/ 28 октября 2009
0 голосов
/ 25 октября 2008

Если ваше абсолютное значение меньше 2 ^ 23 для одного или 2 ^ 52 для двойного, вы можете использовать round (), а затем выполнить сравнение. Большие значения не могут быть точно сохранены, и это открывается для ситуаций, когда N == N + 1.

...