Я хочу судить, равны ли два числа с плавающей точкой.
Нет, вы этого не делаете. Что вы на самом деле пытаетесь сделать, это проверить, равны ли два действительных числа a и b , когда у вас есть только два числа a
и b
, где a
и b
являются результатами операций с плавающей точкой, но a и b являются результатами математики действительных чисел.
Два объекта с плавающей точкой сравниваются равными, если и только если они представляют равные числа. Итак, если вы пытаетесь определить, равны ли два числа с плавающей запятой, все, что нужно, - это оценить a == b
Это оценивается как истина, если и только если a
и b
равны. Таким образом, «сравнение чисел с плавающей точкой» легко. Но вы хотите «сравнить два действительных числа, которые были бы у меня, если бы я использовал арифметику действительных чисел c, но у меня были только числа с плавающей запятой», и это нелегко.
Нормальная операция должна быть fabs (a - b)
Нет, это не нормальная операция. Не существует общего решения для сравнения чисел с плавающей запятой, которые содержат ошибки предыдущих операций. . Я уже писал об этом здесь , здесь и здесь .
определение в вики:
DBL_MIN - минимальное нормализованное положительное значение double;
DBL_EPSILON - разница между 1,0 и следующим представимым значением double.
Согласно определению, приведенному выше, DBL_EPSILON является минимальной точностью двойного значения зачем там DBL_MIN? Какая связь между DBL_MIN и DBL_EPSILON?
В вашем вопросе не указано, какой язык программирования или реализацию вы используете, поэтому мы не знаем точно, что используется для типа double
, который вы используете , Тем не менее, IEEE-754 64-битная двоичная с плавающей точкой является повсеместным. В этом формате числа представлены знаком, 53-битным значением и показателем степени от двух до -1022 до +1023. (Значениеи - это кодирование с использованием как 52-битного поля, так и некоторой информации из поля экспоненты, поэтому многие люди называют его 52-битным значением, но это неверно. Только основное поле для кодирования - 52 бита. фактическая значимость - 53 бита.) Этой информации о значении и с диапазоном экспоненты достаточно, чтобы понять DBL_MIN
и DBL_EPSILON
, поэтому я не буду обсуждать формат кодирования в этом ответе. Тем не менее, я укажу, что есть нормальные значения и субнормальные значения. Для нормальных значений: значение и значения задается двоичной цифрой «1». за ним следуют 52 бита после точки радиуса (52 бита в значимом поле). Для субнормальных значений - значение и значение, заданные «0». сопровождается 52 битами. Нормальные и субнормальные значения различаются по значению в поле экспоненты.
DBL_MIN
- минимальное нормальное положительное значение. Таким образом, он имеет наименьшее нормальное значение и значение, заданное как «1,000000000000000000000000000000000000000000000000000000000000000000», что равно 1, а наименьший показатель степени - –1022. Таким образом, это + 1 • 2 -1022 , что составляет около 2,2 • 10 -308 .
DBL_EPSILON
- это разница между одним и следующим представимым значением в формате с плавающей запятой. Следующее значение задается значением и двоичным «1.0000000000000000000000000000000000000000000000000001», что равно 1 + 2 −52 . Итак, DBL_EPSILON
равно 2 −52 .
Что из этого следует использовать для сравнения по допускам? Ни. Чтобы получить a
и b
, предположительно вы выполнили некоторую операцию с плавающей точкой. В каждой из этих операций могла быть какая-то ошибка. Арифметика с плавающей точкой c приблизительно реальная арифметика c. Для каждой элементарной операции арифметика с плавающей точкой c дает вам представимое значение, которое является ближайшим к результату действительного числа. (Обычно это ближайший в любом направлении, но могут быть доступны режимы направленного округления для выбора предпочтительного направления.) Когда этот представимый результат отличается от результата действительного числа, это различие называется ошибкой округления. В режиме округления до ближайшего, ошибка округления может, как правило, составлять до 1/2 расстояния между представимыми числами в этой окрестности.
Когда вы выполняете более одной операции с плавающей запятой, эти округления ошибки составные. Они могут накапливаться или отменяться. Каждая ошибка мала по сравнению с непосредственным результатом, но, поскольку это число используется в дальнейших вычислениях, конечный результат вычислений может быть небольшим, поэтому ошибки, возникшие в ходе вычислений, могут быть большими по сравнению с окончательным результатом.
Понимание того, какой может быть последняя ошибка, является сложной проблемой в целом. Для этого есть целая область исследования, численный анализ . Это означает, что не может быть никаких общих рекомендаций о том, какой допуск использовать при попытке сравнить числа с плавающей запятой так, как вы хотите. Это требует изучения конкретной проблемы. Кроме того, если вы выясните, что результаты с плавающей точкой a
и b
могут находиться на некотором расстоянии d
друг от друга, даже если результаты действительных чисел a и b будут быть равным, это не значит, что сравнивать a
и b
с допуском d
- правильное решение. Это гарантирует, что вы не получите ложных негативов - каждый раз, когда a и b равны, ваше сравнение a
и b
возвращает true. Однако это позволит вам получить ложные срабатывания - иногда, когда a и b не равны, ваше сравнение a
и b
возвращает true.
Это еще одна причина, по которой не может быть общего совета по сравнению чисел с плавающей точкой. Во-первых, ошибки, которые возникают, являются специфическими для каждого вычисления. Во-вторых, устранение ложных отрицательных результатов требует разрешения ложных положительных результатов, и то, является ли это приемлемым или нет, зависит от приложения. Так что это не может быть дано как общий совет.