【问题标题】:Why does Integer.MAX_VALUE*2 returns -2? [duplicate]为什么 Integer.MAX_VALUE*2 返回 -2? [复制]
【发布时间】:2018-12-05 19:45:02
【问题描述】:

我正在寻找i 的值,其中i==i+1 应始终为true。其他一些人使用doublefloat 来找到问题的解决方案。

我试图回答有关堆栈溢出的问题。并考虑了整数,试图看看这是否也可能。

但是在多次操作Integer.MAX_VALUEInteger.MIN_VALUE 时,我发现了这种奇怪的行为:

Integer.MAX_VALUE + 1 == Integer.MIN_VALUE

但是Integer.MAX_VALUE * 2 == -2Integer.MAX_VALUE * 4 == -4

仅当我使用偶数(例如 (2,4,6,8,10,12...))时才会发生这种情况。当我使用除 1 以外的奇数值时,会发生这种情况:

Integer.MAX_VALUE * n == Integer.MAX_VALUE - n + 1 其中n != Integer.MIN_VALUEn > Integer.MIN_VALUE

为什么会这样?有什么我想念的吗?

编辑:我看到有人将问题标记为重复但导航到引用的链接,我的问题不同。

如果溢出,它会回到最小值并从那里继续。如果它下溢,它会回到最大值并>从那里继续。

我已经仔细阅读了那里的答案,但没有人解释原因:

如果 x 是偶数,

Integer.MAX_VALUE*x 应该是 -x,如果 y 是奇数,Integer.MAX_VALUE*y 应该是 Integer.MAX_VALUE-y+1

这正是我最困惑的地方。

【问题讨论】:

  • 你不清楚哪一部分?
  • 在哪里Integer.MAX_VALUE*2==-2Integer.MAX_VALUE*3==2147483645 至少也应该是-3?
  • 点明白了......有趣的问题,从来没有想过它

标签: java integer


【解决方案1】:

这是因为 Java 的有符号整数遵循 two's complement 表示。

在二进制补码表示中,负数表示为其对应正值的N补码,即它们的和模2n sup> 为 0。

Integer.MAX_VALUE2147483647(十六进制 0x7FFFFFFF)。 相乘时溢出,剩下的是最低的 32 位(即模 232):

0x7FFFFFFF * 2 = 0x0FFFFFFFE (mod32 = 0xFFFFFFFE = -2)
0x7FFFFFFF * 3 = 0x17FFFFFFD (mod32 = 0x7FFFFFFD = 2147483645)
0x7FFFFFFF * 4 = 0x1FFFFFFFC (mod32 = 0xFFFFFFFC = -4)
0x7FFFFFFF * 5 = 0x27FFFFFFB (mod32 = 0x7FFFFFFB = 2147483643)
0x7FFFFFFF * 6 = 0x2FFFFFFFA (mod32 = 0xFFFFFFFA = -6)
0x7FFFFFFF * 7 = 0x37FFFFFF9 (mod32 = 0x7FFFFFF9 = 2147483641)

二进制补码表示的一个有趣特性是最高位对应于值的符号

注意最左边的 7 如何导致 0/1 位 31 交替。该位恰好控制结果的符号,因此是交替符号。

为什么0x7FFFFFFF * 2-2 是因为0x7FFFFFFF 在 31 位表示(没有溢出的最大可能表示)中是-1。并且 -1 * 2 = -2。

如果你取Long.MAX_VALUE 并将结果转换为int,你可以获得类似的结果:

long x = Long.MAX_VALUE;
for (int i = 2; i < 8; i++) {
    System.out.println((int)(x * i));
}

只打印:

-2
-3
-4
-5
-6
-7

现在第 31 位不再交替,所以我们得到了稳定的结果。

【讨论】:

    【解决方案2】:

    2147483647 是最大值,现在尝试执行以下指令集:

    int i = 2147483647;
    i++;
    System.out.println(i);//prints -2147483647 as the 32 bit limit exceeds 
    

    2147483647 的二进制等效值为 01111111111111111111111111111111
    2的二进制等价物是00000000000000000000000000000010

    二进制加法是110000000000000000000000000000000

    注意:左边最后一位代表符号,int 是 32 位有符号整数

    因此,数字变为-2147483647

    i++;
    System.out.println(i); // prints -2147483647
    

    在同一行上,2147483647 * 2 实际上是 -> 2147483647 + 2147483647

    int j = 2147483647;
    j += 2147483647;
    System.out.println(j); // prints -2
    

    然后你就回答了。 现在当你做2147483647 * 3

    它是:

    2147483647 + 2147483647 + 2147483647 = -2 + 2147483647 = 2147483645

    【讨论】:

      猜你喜欢
      • 2012-10-13
      • 2016-07-19
      • 2019-01-09
      • 2015-07-23
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 2012-12-12
      • 2011-06-15
      相关资源
      最近更新 更多