【问题标题】:How precision of floating-point works exactly in practical examples?在实际示例中,浮点精度如何准确工作?
【发布时间】:2018-09-10 04:33:02
【问题描述】:

我认为浮点精度是 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 floating-point precision


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 2018-05-09
    • 1970-01-01
    • 2021-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多