我认为浮点精度是7位小数/位(包括整数和小数部分)——这里我的意思是基数10位7位——我可以在代码编辑器的浮点文字中键入这7位数字。这意味着如果我在两个数字中有7个有效数字(小数点之前和之后),这两个数字将始终不同。
但正如我所见,两个7位有效数字的数字有时不同,有时相同!!!
1)我哪里错了?
2)下面例子中的模式和原理是什么?为什么相同的7位精度组合有时被视为不同,而其他时间被视为相同?
float f01 = 90.000_001f;
float f02 = 90.000_002f; // f01 == f02 is TRUE ! (CORRECT RESULT)
float f03 = 90.000_001f;
float f04 = 90.000_003f; // f03 == f04 is TRUE ! (CORRECT RESULT)
float f1 = 90.000_001f;
float f2 = 90.000_004f; // FALSE (INCORRECT RESULT)
float f3 = 90.000_002f;
float f4 = 90.000_009f; // FALSE (INCORRECT RESULT)
float f5 = 90.000_009f;
float f6 = 90.000_000f; // FALSE (INCORRECT RESULT)
float f7 = 90.000_001f;
float f8 = 90.000_009f; // FALSE (INCORRECT RESULT)
小数点后七位是一个方便的经验法则,但这不是真正发生的事情。Java的flot
是一种32位二进制浮点格式,遵循IEEE-754标准。编码有1个符号位,23位尾数,8位指数,所以你的值是科学记数法,二进制:
f = +/- mantissa * 2^exponent
将您的值转换为这种格式,您应该能够看到发生了什么:
90.000001 = 0(sign) 10000101(exponent) 01101000000000000000000(mantissa)
90.000003 = 0(sign) 10000101(exponent) 01101000000000000000000(mantissa)
90.000004 = 0(sign) 10000101(exponent) 01101000000000000000001(mantissa)
如果您想进一步探索,这是一个比较编码值的方便工具:https://www.h-schmidt.net/FloatConverter/IEEE754.html
在实践中,解决方案是永远不要使用==
运算符来比较浮点值,始终以精度比较浮点数:
Math.abs(x - y) < epsilon