Не сравнивать десятичные дробные строки FPU на равенство
Проблема в том, что сравнение равенства плавающего или двойного значения с десятичной константой, содержащей дробь, редко бывает успешным.
Очень немногие десятичные дроби имеют точные значения в двоичном представлении FP, поэтому сравнения на равенство обычно обречены. *
Чтобы ответить на ваш точный вопрос, 2
исходит из немного другого преобразования десятичной дробной строки в формат Float
. Поскольку дробь не может быть представлена точно, возможно, что два вычисления будут учитывать различную степень точности в промежуточных вычислениях и в конечном итоге в конечном итоге округлять результат в 52-битную мантиссу с двойной точностью IEEE 754 по-разному. Это вряд ли имеет значение, потому что не является точным представлением в любом случае, но одно, вероятно, более неправильно, чем другое.
В частности, ваш 1876.8
не может быть точно представлен объектом FP, фактически между 0,01 и 0,99, только 0,25, 0,50 и 0,75 имеют точные двоичные представления. Все остальные, включая 1876,8, повторяются вечно и округляются до 52 бит. Это примерно половина причины того, что BigDecimal даже существует. (Другая половина причины - фиксированная точность данных FP: иногда вам нужно больше.)
Таким образом, результат, который вы получаете при сравнении фактического машинного значения с десятичной строковой константой, зависит от каждого отдельного бита в двоичной дроби ... вплоть до 1/2 52 ... и даже затем требуется округление.
Если есть хоть что-то, даже малейшее (хе-хе, бит, извините) несовершенное в процессе, который произвел число, или код входного преобразования, или что-либо еще вовлеченное, они не будут выглядеть точно равны.
Можно даже привести аргумент, что сравнение должно всегда терпеть неудачу, потому что ни один FPU в формате IEEE не может даже точно представить это число. Они действительно не равны, хотя выглядят так. Слева ваша десятичная строка была преобразована в двоичную строку, и большинство чисел просто не преобразуются точно. Справа это все еще десятичная строка.
Не смешивайте поплавки с BigDecimal, просто сравните один BigDecimal с другим BigDecimal. (Даже если оба операнда являются числами с плавающей запятой, проверка на равенство требует большой осторожности или нечеткого теста. Кроме того, не доверяйте каждой отформатированной цифре: выходное форматирование будет содержать остатки далеко от правой части дроби, поэтому вы обычно не начинаете видеть нули, вы просто видите значения мусора.)
* Проблема: номера машин х / 2 n , а десятичные константы х / (2 n * 5 м ). Ваше значение как знак, показатель степени и мантисса - это бесконечно повторяющаяся 0 10000001001 1101010100110011001100110011001100110011001100110011...
По иронии судьбы, арифметика FP идеально точна, и сравнения равенства работают превосходно, когда значение не имеет дроби.