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

StackOverflow https://stackoverflow.com/questions/236439

Вопрос

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

Спасибо.

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

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

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

Это было полезно?

Решение

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

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

Другие советы

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

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

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

10.19999999

10.20000001

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

10.19

10.20

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top