浮点精度在实际例子中的准确性如何?

时间:2018-03-31 09:18:26

标签: java floating-point precision

我认为浮点精度是7位小数/位数(包括整数和小数部分) - 这里我的意思是base10 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)

1 个答案:

答案 0 :(得分:3)

七位小数是一个方便的经验法则,但它并不是真正发生的事情。 Java的float32-bit binary floating point format, following the IEEE-754 standard。编码有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