java - 浮点精度在实际例子中到底如何工作?

标签 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)

最佳答案

小数点后七位是一个方便的经验法则,但事实并非如此。 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

实际上,解决此问题的方法是永远不要使用 == 运算符来比较浮点值,而应始终将 float 与精度进行比较:

Math.abs(x - y) < epsilon

关于java - 浮点精度在实际例子中到底如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49586191/

相关文章:

java - IPCZQ cookie httpOnly

java - 将 List<Byte> 转换为字符串

c++ - 快速浮点运算的编译指示

scikit-learn - sklearn precision_recall_curve 和阈值

java - 通过jSoup从Div标签获取属性值

java - GlassFish 服务器部署权限被拒绝 :connect, false

r - 为什么这些数字不相等?

c - 使用标准 C 数学库实现 sinpi() 和 cospi()

ios - 为什么我在 GPU 上有很大的精度错误?

precision - 数字系统中的浮点表示