0

在我正在工作的应用程序中,一些数字从长(18 位)转换并保存为浮点/双精度。这些数字类似于参考/ID,但不用于计算。最近我注意到存储为浮点/双精度的数据存在一些差异。我试图了解这种行为是否是由于浮点数称为有效数字,也许是对相同的简单解释。

我基于以下程序的问题是

  1. 输出 no : 5 显示一个非常大的数字(小数点前 39 位)作为浮点的最大值。为什么 float 不能准确显示 7 位以上的内容。这是因为它只支持 6-7 位有效数字。
  2. 输出 no : 10 显示一个非常大的数字作为 double 的最大值。那么为什么 double 无法准确显示 16 位以上的任何内容。这是因为它只支持 15 位有效数字。
  3. 有效数字的真正含义是什么?这是否意味着该数字之后的任何数字无论是在小数点之前还是之后都无法准确表示?

注意:在我对这个主题进行研究之后,我现在明白浮点数本质上是不准确的,不应该用于表示需要准确表示的事物。我仍然对上述行为和有效数字感到有些困惑。

public class Main
{
    public static void main(String[] args) {
        System.out.printf( "1. Float value of 50000000115 is : %,f. Expected output was 50000000115.000000 \n", 50000000115f );
        System.out.printf( "2. Float value of 50000000116 is : %,f. Expected output was 50000000116.000000 \n", 50000000116f );
        System.out.printf( "3. Float value of 50000000117 is : %,f. Expected output was 50000000117.000000 \n\n", 50000000117f );

        System.out.printf( "4. Float value of 2175863596593954381 is : %,f. Expected output was 2175863596593954381.000000 \n\n", 2175863596593954381f );

        System.out.printf( "5. Float.MAX_VALUE: %,f\n\n", Float.MAX_VALUE );

        System.out.printf( "6. Double value of 50000000115 is : %,f\n", 50000000115d );
        System.out.printf( "7. Double value of 50000000116 is : %,f\n", 50000000116d );
        System.out.printf( "8. Double value of 50000000117 is : %,f\n\n", 50000000117d );

        System.out.printf( "9. Double value of 2175863596593954381 is : %,f. Expected output was  2175863596593954381.000000 \n\n", 2175863596593954381d );

        System.out.printf( "10. Double.MAX_VALUE: %,f\n\n", Double.MAX_VALUE );

        System.out.printf( "11. Float value of number gives expected result till 7 digits ie 12345678 is : %,f\n", 12345678f );
        System.out.printf( "12. Float value of number gives expected result till 7 digits ie 11111111 is : %,f\n", 11111111f );
        System.out.printf( "13. Double value of number gives expected result till 16 digits ie 1122334455667788 is : %,f\n", 1122334455667788d );
        System.out.printf( "14. Double value of number gives expected result till 16 digits ie 1111222233334444 is : %,f\n", 1111222233334444d );
    }
}

上述程序的输出

  1. 50000000115 的浮点值为:49,999,998,976.000000。预期输出为 50000000115.000000
  2. 50000000116 的浮点值为:49,999,998,976.000000。预期输出为 50000000116.000000
  3. 50000000117 的浮点值为:49,999,998,976.000000。预期输出为 50000000117.000000

  4. 2175863596593954381 的浮点值为:2,175,863,554,941,386,750.000000。预期产量为 2175863596593954381.000 000

  5. Float.MAX_VALUE: 340,282,346,638,528,860,000,000,000,000,000,000,000.000000

  6. 50000000115 的双倍值是:50,000,000,115.000000

  7. 50000000116 的双倍值是:50,000,000,116.000000
  8. 50000000117 的双倍值是:50,000,000,117.000000

  9. 2175863596593954381 的双精度值为:2,175,863,596,593,954,300.000000。预期输出为 2175863596593954381.0 00000

  10. Double.MAX_VALUE: 179,769,313,486,231,570,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,00 0,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000.000000

  11. 数字的浮点值给出了预期的结果,直到 7 位,即 12345678 是:12,345,678.000000

  12. 数字的浮点值给出了预期的结果,直到 7 位,即 11111111 是:11,111,111.000000
  13. 数字的双值给出预期结果,直到 16 位,即 1122334455667788 是:1,122,334,455,667,788.000000
  14. 数字的双值给出预期结果,直到 16 位,即 1111222233334444 是:1,111,222,233,334,444.000000
4

1 回答 1

3

Java 的Float类型(IEEE-754 binary32)实际上有两个组件:

  • 从 -16,777,215 到 +16,777,215 (2 24 -1)的整数个单位和
  • 一个单位,是 2 104到 2 -149的 2 的幂。

使用将单位数保持在范围内的最小单位(范围内)。

例如,对于 50,000,000,115,我们不能使用 2048 (2 12 ) 的单位大小,因为 50,000,000,115 大约是 2048 的 24,414,062 个单位,比 16,777,215 个单位多。所以我们使用 4096 的单位大小。

50,000,000,115 正好是 4096 的 12,207,031.278076171875 个单位,但我们只能使用整数个单位,所以Float最接近 50,000,000,115 的值是 4096 的 12,207,031 个单位,即 49,999,998,976。

您问题中的其他值的表示方式类似,但 Java 格式化数字的规则%,f导致用于显示该值的十进制数字数量有限。因此,在您的一些示例中,我们看到尾随零,其中内部数字的实际数学值不同。

对于Double(IEEE-754 binary64),两个组件是:

  • 从 -9,007,199,254,740,991 到 +9,007,199,254,740,991 (2 53 -1)的整数个单位和
  • 一个单位,是 2 972到 2 -1074的 2 的幂。
于 2019-09-16T11:36:58.270 回答