【问题标题】:Why is double to int conversion not working as expected in java?为什么 double 到 int 的转换在 java 中不能按预期工作?
【发布时间】:2020-02-03 09:28:49
【问题描述】:

我已经开始阅读 Java8 的文档并尝试了不同的示例代码。发现以下奇怪的行为。

样本1

Double di = new Double(Math.pow(2,32-1));
System.out.printf("%f\n",di.doubleValue()); //2147483648.000000
int a= di.intValue();
System.out.println(a); //2147483647

样本2

Double di = new Double(Math.pow(2,32-1)) - 1.0;
System.out.printf("%f\n",di.doubleValue()); //2147483647.000000
int a= di.intValue();
System.out.println(a); //2147483647

为什么在这两种情况下,int 值都返回相同的值?

【问题讨论】:

  • 试试System.out.println(Integer.MAX_VALUE); ...现在试试System.out.println(Integer.MAX_VALUE + 1); - 你想从那个有效的结果中得到哪个结果?

标签: java type-conversion int range double


【解决方案1】:

int 值不能超过 Integer.MAX_VALUE,正好是 2147483647。 调用intValue()时你自愿放弃所有的尾巴。

【讨论】:

    【解决方案2】:

    请看https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3最后以粗体突出显示的重要部分:

    浮点数到整数类型 T 的窄化转换需要两个步骤:

    在第一步中,浮点数转换为 long(如果 T 为 long)或转换为 int(如果 T 为 byte、short、char 或 int),如下所示:

    如果浮点数为 NaN(第 4.2.3 节),则第一步转换的结果为 int 或 long 0。

    否则,如果浮点数不是无穷大,则浮点值将四舍五入为整数值 V,使用 IEEE 754 向零舍入模式(第 4.2.3 节)向零舍入。那么有两种情况:

    如果T是long,并且这个整数值可以表示为long,那么第一步的结果就是long值V。

    否则,如果这个整数值可以表示为int,那么第一步的结果就是int值V。

    否则,以下两种情况之一必须为真:

    该值一定是太小了(大的负值或负无穷大),第一步的结果是int或long类型的最小可表示值。

    该值一定是太大(一个大的正值或正无穷大),第一步的结果是int或long类型的最大可表示值。

    也就是说,您的 double 值为 2147483648(您可以尝试更高的数字)。最高可表示的值 int int 是 2147483647。这就是你最终得到 2147483647 的原因。

    【讨论】:

      【解决方案3】:

      这是因为Java中int类型的最大值是2147483647。当您调用Double::doubleValue 时,如果您尝试转换的值超出范围并且此方法的docs 说明,它将执行缩小转换:

      在缩小原始转换后将此 Double 的值作为 int 返回。

      它甚至指向描述这种缩小转换的JLS 5.1.3

      转换浮点值需要两个步骤。您看到此值的原因在第一步,点三,选项 b 的句子中进行了解释:

      该值必须太大(一个大的正值或正无穷大),并且第一步的结果是int或long类型的最大可表示值。

      浮点数到整数类型 T 的窄化转换需要两个步骤:

      1. 在第一步中,浮点数转换为 long(如果 T 为 long)或转换为 int(如果 T 为 byte、short、char 或 int),如下所示:

        • 如果浮点数为 NaN(第 4.2.3 节),则第一步转换的结果为 int 或 long 0。

        • 否则,如果浮点数不是无穷大,浮点值将四舍五入为整数值 V,使用 IEEE 754 向零舍入模式(第 4.2.3 节)向零舍入.那么有两种情况:

        • a如果T是long,并且这个整数值可以表示为long,那么第一步的结果就是long值V。

        • b否则,如果这个整数值可以表示为int,那么第一步的结果就是int值V。

        • 否则,以下两种情况之一必须为真:

        • a该值一定是太小了(大的负值或负无穷大),第一步的结果是int或long类型的最小可表示值。

        • b 该值一定是太大(一个大的正值或正无穷大),第一步的结果是int类型的最大可表示值 或长。

      2. 第二步:

        • 如果 T 是 int 或 long,转换的结果就是第一步的结果。

        • 如果 T 是 byte、char 或 short,则转换的结果是第一步的结果缩小转换为 T 类型(第 5.1.3 节)的结果。

      因此,在这种情况下,结果将是int 类型的最大可表示值。

      【讨论】:

        猜你喜欢
        • 2021-10-19
        • 2012-07-24
        • 1970-01-01
        • 2021-02-09
        • 2018-11-15
        • 2021-05-30
        • 2020-03-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多