不要比较 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 ……甚至需要四舍五入。
如果产生数字的过程、输入转换代码或其他任何涉及的过程有任何不完美的地方(呵呵,有点,抱歉),它们看起来不会完全相等。
甚至可以提出比较应该总是失败的论点,因为没有 IEEE 格式的 FPU 甚至可以准确地表示该数字。他们真的是不平等的,即使他们看起来很像。在左侧,您的十进制字符串已转换为二进制字符串,并且大多数数字并未完全转换。在右边,它仍然是一个十进制字符串。
所以不要将浮点数与 BigDecimal 混合,只需将一个 BigDecimal 与另一个 BigDecimal 进行比较。(即使两个操作数都是浮点数,测试相等性也需要非常小心或模糊测试。此外,不要相信每个格式化的数字:输出格式会将余数带离分数的右侧,所以你通常不会开始看到零,你只会看到垃圾值。)
*问题:机器编号是 x/2 n,但十进制常数是 x/(2 n * 5 m )。您作为符号、指数和尾数的值是无限重复的0 10000001001 1101010100110011001100110011001100110011001100110011...
具有讽刺意味的是,FP 算术非常精确,当值没有分数时,等式比较工作得很好。