【问题标题】:Java: Assigning a value too big directly vs. integer wrap aroundJava:直接分配一个太大的值与整数环绕
【发布时间】:2020-03-08 08:11:22
【问题描述】:

我一直在探索 Java 如何处理整数溢出和下溢,我遇到了这两种情况:

如果将超出范围的值直接分配给 int,则可能没有回绕,这取决于转换:

    long tooBigLong=2147483648L;
    int integerL=(int)tooBigLong;

    double tooBigDouble=Math.pow(2, 31);
    int integerD=(int)tooBigDouble;

结果:

Converted from Long to int: -2147483648

Converted from Double to int: 2147483647

似乎只有当我从 Long 转换为 int 时才会发生整数环绕。

但我确实想弄清楚它对于 double 到 int 的转换是如何不起作用的? 谢谢您的帮助!

【问题讨论】:

  • “但我确实想弄清楚它如何不能用于 double 到 int 的转换?”因为语言规范是这么说的。这足以令人满意吗?
  • 那么就足够了。谢谢:)
  • 如果您愿意,我可以推测一下为什么会这样设计,但出于真正的原因,您必须询问语言团队。
  • 我刚刚发现,如果我放弃 Math.pow 并为双精度分配一个 Integer.MAX_VALUE,我会得到一个环绕......我想你是对的,这无法解释无需询问语言开发者!
  • 等等你做了什么?

标签: java type-conversion integer integer-overflow


【解决方案1】:

JLS 指定5.1.3. Narrowing Primitive Conversion 的规则:

将long 转换为int 时:

有符号整数到整数类型 T 的窄化转换只会丢弃除 n 个最低位之外的所有位,其中 n 是用于表示类型 T 的位数。除了可能丢失有关数值,这可能会导致结果值的符号与输入值的符号不同。

因此,在您的示例中,删除原始 long 的前 32 位并保留后 32 位会导致 int 为负数。

将double 转换为int 时:

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

  1. 在第一步中,浮点数转换为 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。

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

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

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

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

突出显示的部分确定(int)tooBigDouble 应导致Integer.MAX_VALUE。对于更高的 double 值,您会得到相同的结果。例如,对于double tooBigDouble=Math.pow(2, 39);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-03
    • 2012-01-08
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多