在Java中,整数是如何在位级别内部表示的?

在Java中,整数是如何在位级别内部表示的?,java,memory,binary,store,twos-complement,Java,Memory,Binary,Store,Twos Complement,我试图理解Java如何在内部存储整数。我知道所有java原语整数都是有符号的(除了short?)。这意味着一个字节中的数字可用位减少了一位 我的问题是,所有的整数(正的和负的)都存储为2的补码,还是只有负数存储在2的补码中 我看到规范上写着x位2的补码号。但我经常感到困惑 例如: int x = 15; // Stored as binary as is? 00000000 00000000 00000000 00001111? int y = -22; // Stored as tw

我试图理解Java如何在内部存储整数。我知道所有java原语整数都是有符号的(除了short?)。这意味着一个字节中的数字可用位减少了一位

我的问题是,所有的整数(正的和负的)都存储为2的补码,还是只有负数存储在2的补码中

我看到规范上写着
x位2的补码号
。但我经常感到困惑

例如:

  int x = 15; // Stored as binary as is?  00000000 00000000 00000000 00001111?
  int y = -22; // Stored as two complemented value? 11111111 11111111 11111111 11101010
编辑

需要明确的是,
x=15

   In binary as is: `00000000 00000000 00000000 00001111'
  Two's complement: `11111111 11111111 11111111 11110001`
因此,如果您的答案是
所有的
数字都存储为2的补码,那么:

  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010
这里的困惑是,符号上写着,两者都是负数。可能是我误读了/误解了吗

编辑 我不确定我的问题是否令人困惑。被迫孤立问题:

我的问题正是:正数是以二进制形式存储的吗,而负数是以两个补码形式存储的?


一些人说所有的整数都存储在2的补码中,一个回答说只有负数存储在2的补码中。

根据java,所有整数都是有符号的,并以2的补码格式存储。不确定其可靠性。

Oracle提供了一些关于Java的文档,您可能会感兴趣。具体而言:

int:int数据类型是一个32位有符号2的补码整数。它的最小值为-2147483648,最大值为2147483647(含)


顺便说一句,short也存储为two的补码。

我运行了以下程序来了解它

public class Negative {
    public static void main(String[] args) {
        int i =10;
        int j = -10;

        System.out.println(Integer.toBinaryString(i));
        System.out.println(Integer.toBinaryString(j));
    }
}
输出为

1010
11111111111111111111111111110110

从输出来看,它似乎一直在使用二的补码。

让我们从总结Java基本数据类型开始:

字节:字节数据类型是一个8位有符号的两个补码整数

Short:Short数据类型是一个16位有符号的二的补码整数

int:int数据类型是一个32位有符号的2的补码整数

long:long数据类型是一个64位有符号的2的补码整数

浮点:浮点数据类型是单精度32位IEEE 754浮点

double:double数据类型是双精度64位IEEE 754浮点

布尔:布尔数据类型表示一位信息

字符:字符数据类型是单个16位Unicode字符

两个补码

“一个很好的例子是,通过注意256=255+1和(255)来实现与二的补码的关系− x) 是x的1的补码

0000 0111=7二的补码是11111001=-7

其工作方式是MSB(最高有效位)接收负值,因此在上述情况下

-7=1001=-8+0+0+1

正整数通常存储为简单的二进制数(1是1,10是2,11是3,依此类推)

负整数存储为两个绝对值的补码。使用此表示法时,两个正数的补码是负数

因为这个答案给了我几分,所以我决定补充更多的信息

更详细的答案: 在其他方法中,有四种主要方法以二进制表示正数和负数,即:

  • 符号震级
  • 补语
  • 二元补码
  • 偏倚
  • 1.符号震级

    使用最高有效位表示符号,剩余位用于表示绝对值。其中0表示正数1表示负数,例如:

    1011 = -3
    0011 = +3
    
    这种表示法更简单。但是,不能像添加十进制数那样添加二进制数,这使得在硬件级别实现起来更困难。此外,这种方法使用两种二进制模式来表示0、-0(1000)+0(0000)

    一个人的补语

    在这种表示法中,我们将给定数字的所有位反转,以找出其互补位。例如:

    010 = 2, so -2 = 101 (inverting all bits).
    
    这种表示法的问题是仍然存在两位模式来表示0,负0(1000)正0(0000)

    3.二的补语

    为了找到一个数字的负数,在这个表示法中,我们将所有的位反转,然后加上一位。加上一位解决了两位模式代表0的问题。在这个表示法中,我们只有一个模式代表0 0(0000)

    例如,我们希望使用4位查找4(十进制)的二进制负表示。首先,我们将4转换为二进制:

    4 = 0100
    
    然后我们把所有的位都倒过来

    0100 -> 1011
    
    最后,我们添加一位

    1011 + 1 = 1100.
    
    因此,如果我们使用4位的二元补码表示,1100相当于十进制中的-4

    找到互补项的更快方法是将第一个位固定为值1,然后将剩余的位反转。在上面的示例中,它类似于:

    0100 -> 1100
    ^^ 
    ||-(fixing this value)
    |--(inverting this one)
    
    2的补码表示法,除了0只有一个表示法外,它还以与十进制相同的方式添加两个二进制值,即具有不同符号的偶数。不过,有必要检查溢出情况

    4.偏见

    此表示法用于表示IEEE 754浮点范数中的指数。其优点是所有位均为零的二进制值表示最小值。且
    +1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
    converting to binary
    1000 0001
    
    Bit#    Weight
    31      -2^31
    30       2^30
    29       2^29
    ...      ...
    2        2^2
    1        2^1
    0        2^0
    
    Binary    Weighted sum            Integer value
    0000       0 + 0 + 0 + 0           0
    0001       0 + 0 + 0 + 2^0         1
    0010       0 + 0 + 2^1 + 0         2
    0011       0 + 0 + 2^1 + 2^0       3
    0100       0 + 2^2 + 0 + 0         4
    0101       0 + 2^2 + 0 + 2^0       5
    0110       0 + 2^2 + 2^1 + 0       6
    0111       0 + 2^2 + 2^1 + 2^0     7 -> the most positive value
    1000      -2^3 + 0 + 0 + 0        -8 -> the most negative value
    1001      -2^3 + 0 + 0 + 2^0      -7
    1010      -2^3 + 0 + 2^1 + 0      -6
    1011      -2^3 + 0 + 2^1 + 2^0    -5
    1100      -2^3 + 2^2 + 0 + 0      -4
    1101      -2^3 + 2^2 + 0 + 2^0    -3
    1110      -2^3 + 2^2 + 2^1 + 0    -2
    1111      -2^3 + 2^2 + 2^1 + 2^0  -1
    
    x + ~x = 1111 1111 1111 1111 1111 1111 1111 1111
    x + ~x + 1 =   1111 1111 1111 1111 1111 1111 1111 1111 + 1
               = 1 0000 0000 0000 0000 0000 0000 0000 0000
    
    x + ~x + 1 = 0
    -x = ~x + 1
    
    e.g) For +ve number 10; byte representation will be like 0-000 0010 
                                                   (0 - MSB will represent that it is +ve).
    So while retrieving based on MSB; it says it is +ve, 
    so the value will be taken as it is. 
    
      0-000 0010  -> (1's complement) -> 0-111 1101 
                  -> (2's complement) 0-111 1101 + 1 -> 0-111 1110
      Now MSB will be set to one, since it is negative no -> 1-111 1110
    
      1-111 1110  --> 1-000 0001 + 1 --> 1-000 0010
      Since MSB representing this is negative 10 --> hence  -10 will be retrived.
    
    (MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
    
      0-000 000 1000 0010     (MSB = 0)
    
     1-000 0010  -> (1's complement) -> 1-111 1101 
                 -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110
                   = -126
    
    (byte)-1       -> 0-000 0001 (2's Comp) -> 0-111 1111 (add sign) -> 1-111 1111
    (char)(byte)-1 -> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 
    
    (short)(byte)-1-> 1-111 1111 1111 1111  (sign bit is carry forwarded on left) 
    
    (int)(char)(byte)-1 -> 0-0000000 00000000 11111111 11111111  = 65535
    since char is unsigned; MSB won't be carry forwarded. 
    
    (int)(Short)(byte)-1 -> 1-1111111 11111111 11111111 11111111 = -1
    since short is signed; MSB is be carry forwarded.