【问题标题】:Why when 127*2 the result is -2 when we change to byte?为什么当我们更改为字节时,当 127*2 时结果为 -2?
【发布时间】:2013-11-16 03:19:07
【问题描述】:

这是我的代码:

public class test {

  public static void main(String[] args) {
    byte a=(byte)127, b=2;    
    byte c=(byte)(a*b);

    System.out.println(c);
  }    
}

为什么结果是-2?

【问题讨论】:

  • 一个字节只有八位长。
  • 字节溢出,二进制补码变为负数
  • 您是否知道您的(64 位?)CPU 将很难摆弄字节?

标签: java


【解决方案1】:

我想你想问的是为什么 8 位有符号整数的溢出会变成负数。
由于CPU中没有8bits ALU,所以8bits会扩展为32bits,运算后将低8bits返回给用户。
在 CPU 中:0000_007F * 0000_0002 = 0000_00FE
这是有符号 8 位的溢出,但该值已经计算过了。
所以返回值为FE。
对于 8 位签名,FE 是 -2。

【讨论】:

    【解决方案2】:

    8 位中的 127 用二进制表示如下:

    01111111
    

    乘以 2,得到:

    11111110
    

    (以 10 为底乘以 10 时,所有数字都可以左移到下一个位置。二进制乘以 2 自然也是如此)

    Java 使用 2 的补码来表示负数。基本上,最左边的位是符号位(0 表示 +,1 表示 -)。要将正数转换为负数,请将所有位翻转并加一位。

    示例:00000010 = 2,翻转位:11111101,然后加一个:11111110 = -2。这和上面的127*2是一样的。

    【讨论】:

      【解决方案3】:

      a * b 是 254,所以你的代码是:

      byte c=(byte)254;

      十进制的254是二进制的11111110,即:-2。为什么?

      首先,这个数是负数,因为它以1(二进制补码)开头,那么:

      ¬ 1 1 1 1 1 1 1 0 是0 0 0 0 0 0 0 1。

      0 0 0 0 0 0 0 1
                    1 +
      ---------------
      0 0 0 0 0 0 1 0 
      

      这表示十进制的 2,但记得 MSB 是 1 吗?所以最终结果是-2。

      【讨论】:

        【解决方案4】:

        因为a*b会产生一个临时的int变量,即254,即1111 1110。当转换为byte时,这将作为一个signed处理价值。 MSB 为 1,因此其值为负数,值为 -((((inv)111 1110) + 1) = -(((000 0001) + 1) = -2。

        【讨论】:

          【解决方案5】:

          因为字节是有符号的,而不是无符号的。

          254 = FE = 1111 1110

          第一个'1'表示数字为负数。

          【讨论】:

            【解决方案6】:

            由于 byte 是有符号类型 2 * 127 是二进制“11111110”,即two's complement for -2。

            【讨论】:

              猜你喜欢
              • 2012-08-23
              • 2023-02-11
              • 2019-06-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-03-19
              相关资源
              最近更新 更多