java - java中的大 float 和 double 打印/保留不正确。此行为是由于有效位数所致吗?

标签 java math floating-point precision real-number

在一个应用程序中,我正在将一些数字从长(18 位数字)转换并保存为浮点/ double 。这些数字类似于引用/ID,但不用于计算。最近我注意到存储为浮点/ double 的数据存在一些差异。我试图了解这种行为是否是由于 float 所谓的有效数字所致,也许还有一个简单的解释。

我根据以下程序提出的问题是

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

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

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 的 double 值为:50,000,000,115.000000

  7. 50000000116 的 double 值为:50,000,000,116.000000
  8. 50000000117 的 double 值为:50,000,000,117.000000

  9. 2175863596593954381 的 double 值为: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

最佳答案

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

  • 从 −16,777,215 到 +16,777,215 的整数个单位 (224−1) 和
  • 2 的幂的单位,从 2104 到 2−149

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

例如,对于 50,000,000,115,我们不能使用 2048 (212) 的单位大小,因为 50,000,000,115 约为 2048 的 24,414,062 个单位,超过 16,777,215 个单位。因此我们使用单位大小 4096。

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

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

对于 Double(IEEE-754 二进制 64),两个组件是:

  • 从 −9,007,199,254,740,991 到 +9,007,199,254,740,991 (253−1) 的整数个单位,并且
  • 2 的幂,从 2972 到 2−1074

关于java - java中的大 float 和 double 打印/保留不正确。此行为是由于有效位数所致吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57954475/

相关文章:

java - java中的输出(printf)中的终止符(number).(number)[a](number)[d0]是什么意思?

java - 我可以确定正则表达式模式匹配的第一个字符集吗?

Java:一个指向可达对象的无法到达的对象会被垃圾收集吗?

javascript - 围绕一个点旋转,离它越来越近

c++ - GLSL 330 矩阵计算错误{无编译错误}

java - 检查两个 float/double 值是否完全相等

Java RegEx 查找方法名称

math - 将一组共面的 3D 点映射到它们的平面 2D 坐标

android - std::min 的参数顺序更改浮点的编译器输出

java - Java中float和double的包含范围是多少?