【问题标题】:Why Integer.toBinaryString returns 32 bits if the argument is negative?如果参数为负,为什么 Integer.toBinaryString 返回 32 位?
【发布时间】:2014-08-18 20:50:25
【问题描述】:

我只是在搞乱Integer.toBinaryString(int) 方法。

当我传递一个正数比如 7 时,它输出 111 但是当我传递负数 7 时,它输出 11111111111111111111111111111001。我知道 Java 使用 2 的补码来表示负数,但为什么是 32 位(我也知道 int 是 32 位长但不适合答案)?

【问题讨论】:

  • 所有 int 值都是 32 位的,它会删除前导零,但对于负数,它将设置一个最高位。
  • 这里没有加起来。你说你了解 2 的补码,但你不明白为什么负数的前导 1?
  • @OliCharlesworth:我的意思是你为什么要将其余所有位添加为 1 而不是一个有符号位?
  • @Vwin:因为这就是 2 的补码的工作原理。
  • 我明白你的意思,但你说错了。 2 的补码与前面加 1 无关。这是因为正如@peter 所说,例如 7 的数字有前导 0,它们被反转为所有 1

标签: java integer bit-manipulation


【解决方案1】:

好吧,所以我做了一些挖掘......

我写了一个小程序,可能和你做的差不多。

public class IntTest {
    public static void main(String[] args){
        int a = 7;
        int b = -7;
        System.out.println(Integer.toBinaryString(a));
        System.out.println(Integer.toBinaryString(b));
    }
}

我的输出:

111

1111111111111111111111111111001

因此,如果 111 前面有 29 个“0”,则它是相同的。那只是浪费空间和时间。

如果我们按照这个人here 的二进制恭维说明进行操作,您可以看到我们必须做的是翻转位(零变为一,一变为零),然后我们将结果加 1。

所以 0000 0000 0000 0000 0000 0000 0000 0111 变成 1111 1111 1111 1111 1111 1111 1111 1001

这些不能被丢弃,因为它们在二进制恭维表示中很重要。这就是为什么在第二种情况下你有 32 位。

希望这会有所帮助! -- 开启代码!!!

【讨论】:

  • 你是对的。这很令人困惑,因为没有显示前导 0。
  • 是的,可以把它想象成 500 代表 00500,你可以在 5 前面放尽可能多的零,它不会改变它的值。
【解决方案2】:

因为 Java 整数是 32 位签名的。如果使用负数,则第一位必须为 1。

System.out.println(Integer.toBinaryString(0));
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE)); // 31 bits
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE - 1)); // 31 bits
System.out.println(Integer.toBinaryString(Integer.MAX_VALUE + 1)); // 32 bits
System.out.println(Integer.SIZE);

输出是

0
1111111111111111111111111111111
1111111111111111111111111111110
10000000000000000000000000000000
32

请注意,Integer.MAX_VALUE + 1Integer.MIN_VALUE(并且它有一个额外的位)。

【讨论】:

  • 但我的问题是为什么有这么多 1。我得到了我的答案,这是因为正数本身具有前导 0,当反转时全为 1。由于 Java 不显示正数的前导 0,因此产生了冲突。
【解决方案3】:

它会输出最小的数字,去掉前导零。在负数的情况下,32 位中的第一位是符号位(即 -1 是 1,30 个零和另一个 1)。因此,由于它必须输出符号位(它很重要),所以它输出所有 32 位。

这是使用符号位和无符号移位运算符的一个很酷的半相关示例:)。如果你这样做:

int x = {positive_value};
int y = {other_positive_value};
int avg = (x + y) >>> 1;

x 和 y 整数都可以使用前 31 位,因为第 32 位是符​​号。这样,如果它们溢出,它们会溢出到符号位并使值变为负。 >>> 是一个无符号移位运算符,它将值向右移动一位,这实际上是一个除以二和下限运算,它给出了一个适当的平均值。

另一方面,如果你这样做了:

int x = {value};
int y = {other_value};
int avg = (x + y) / 2;

如果出现溢出,你会得到错误的结果,因为你将负值除以 2。

【讨论】:

    猜你喜欢
    • 2022-09-24
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 2018-01-29
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多