Bitwise op意外地变为负面

时间:2014-09-18 17:21:48

标签: java bit-manipulation

有人可以向我解释为什么我会得到这些结果吗?

public static int ipv4ToInt(String address) {
    int result = 0;

    // iterate over each octet
    for(String part : address.split(Pattern.quote("."))) {

        // shift the previously parsed bits over by 1 byte
        result = result << 8;

        System.out.printf("shift = %d\n", result);

        // set the low order bits to the current octet
        result |= Integer.parseInt(part);

        System.out.printf("result = %d\n", result);
    }
    return result;
}

对于ipv4ToInt(&#34; 10.35.41.134&#34;),我得到:

  

shift = 0
  结果= 10
  shift = 2560
  结果= 2595
  shift = 664320
  结果= 664361
  shift = 170076416
  结果= 170076550
  10.35.41.134 = 170076550

这与我自己进行数学运算时得到的结果相同。

对于ipv4ToInt(&#34; 192.168.0.1&#34;),我得到:

  

shift = 0
  结果= 192
  shift = 49152
  结果= 49320
  shift = 12625920
  结果= 12625920
  shift = -1062731776
  结果= -1062731775
  192.168.0.1 = -1062731775

对于这个,当我手动进行数学运算时,我得到3232235521。

有趣的是:
3232235521 = 11000000101010000000000000000001
当我输入1062731775进入我的Windows calc并点击+/-按钮时,我得到:
-1062731775 = 11111111111111111111111111111111 11000000101010000000000000000001

这个功能仍然可以用于我的目的,但是我真的好奇地知道为什么当我做最后一次移位时,地球上的结果会变为负面?

4 个答案:

答案 0 :(得分:5)

因为你的情况下有点溢出!

在Java中,整数也是32位,范围是-2,147,483,648到2,147,483,647。

12625920 << 8越过2 ^ 31-1的限制,因此结果变为负数......

结果只是从-ve侧翻了过来,因此,从积极方面留下的任何范围都伴随着来自消极方面的那么多!!!

正如大家所建议的,你应该使用long变量来避免溢出!

答案 1 :(得分:1)

java中的所有原语都是签名的 - 它们可以是正面的也可以是负面的。最高位用于控制它,因此当它被设置时,数字变为负数。

尝试使用long代替 - 这将为您提供所需的结果,因为long可以更大,而不会出现溢出。

答案 2 :(得分:1)

11000000101010000000000000000001是32位。它代表的值取决于你如何解释这些位:

  • 作为32位有符号整数,它是负数(因为最左边的位是1)
  • 作为32位无符号整数,它是正的(与所有其他无符号整数一样)
  • 作为long(有符号或无符号)的低位,它将给出一个正值(如果最左边的位保持为0)

Java使用有符号整数,因此如果您打印该值,您将看到一个负数。这并不意味着你的位错了。

答案 3 :(得分:0)

仅对打印很重要,您可以使用这些方法打印正整数:

1)将结果更改为long(java将为您完成工作)。

2)自己将signed int作为unsigned int处理(可能使方法为int2string(int n)或toString(int n)。

3)Integer.toUnsignedString(int)你正在使用java 8。

据我了解,你正在解析一个IP地址,记住,java使用签名数据类型,你不能有32位整数。

将结果更改为long以解决此问题。