在Java中,整数是如何内部表示的?
我想了解Java如何在内部存储整数。 我知道所有的Java原始整数签名,(除短吗?)。 这意味着数字的一个字节中less了一位。
我的问题是,所有的整数(正数和负数)存储为二进制补码还是只有负数的二进制补码?
我看到规格说x bit two's complement number
。 但是我经常感到困惑。
例如:
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`
所以如果你的答案是all
数字都被存储为二进制补码,那么:
int x = 15; // 11111111 11111111 11111111 11110001 int y = -22 // 11111111 11111111 11111111 11101010
这里的混淆再次是标志说,都是负数。 可能是我误读/误解了吗?
编辑不知道我的问题是混乱。 被迫孤立的问题:
我的问题恰恰是:正数以binary as is
forms存储,而负数以binary as is
forms存储?
有人说所有的都是二进制补码,一个答案只有负数存储为二进制补码。
让我们从总结Java原始数据types开始:
字节 :字节数据types是一个8位有符号的二进制补码整数 。
Short :短数据types是一个16位有符号的二进制补码整数 。
int: Int数据types是一个32位有符号的二进制补码整数 。
long: long数据types是一个64位有符号的二进制补码整数 。
float: Float数据types是一个单精度的32位IEEE 754浮点数 。
double :double数据types是一个双精度的64位IEEE 754浮点数 。
布尔值:布尔型数据types表示一位信息 。
char: char数据types是一个16位的Unicode字符 。
资源
两个补码
“ 维基的一个很好的例子是,与二进制补码的关系是通过注意到256 = 255 + 1来实现的,(255-x)是x的补码
0000 0111 = 7二进制补码是1111 1001 = -7
它的工作方式是msb(最高有效位)在上面的情况下收到一个负值
-7 = 1001 = -8 + 0 + 0 + 1
通常将正整数存储为简单的二进制数(1是1,10是2,11是3等等)。
负整数作为其绝对值的二进制补码存储。 当使用这个符号时,正数的二进制补码是负数。
资源
由于我收到了这个答案的几点,我决定添加更多的信息。
更详细的答案:
除了其他之外,还有四种主要方法来表示二进制的正数和负数,即:
- 签名幅度
- 一个人的补充
- 两个的补充
- 偏压
1.签名幅度
使用最高有效位来表示符号,其余位用来表示绝对值。 其中0表示正数 , 1表示负数 ,例如:
1011 = -3 0011 = +3
这种表示更简单。 但是,不能像添加十进制数字那样添加二进制数字,因此难以在硬件级别实现。 此外,这种方法使用两个二进制模式来表示0,100 … 0和0 …. 0。
2.补货
在这个表示中,我们反转给定数字的所有位以找出它的互补。 举个例子:
010 = 2, so -2 = 101 (inverting all bits).
这种表示的问题是仍然存在两个比特模式来表示0(00..0和11..1)
3.两个人的补充
为了find一个数的负数,在这个表示中,我们将所有的位反转,然后添加一位。 加一位解决了两个位模式代表0的问题。在这个表示中,我们只有一个(00 … 0)。
例如,我们想用4位find4(十进制)的二进制负表示。 首先我们将4转换成二进制:
4 = 0100
然后我们倒置所有的位
0100 -> 1011
最后我们加一点
1011 + 1 = 1100.
所以如果我们使用4位的Two's Complement二进制表示,那么1100相当于十进制的-4。
find互补的更快的方法是将第一位固定为值1并反转剩余的位。 在上面的例子中,它会是这样的:
0100 -> 1100 ^^ ||-(fixing this value) |--(inverting this one)
二的补码表示法,除了只有一个0的表示forms外,还以与十进制数相同的方式添加了两个二进制数值,即不同符号的偶数。 不过,有必要检查溢出情况。
4.偏见
这个表示用于表示浮点的IEEE 754标准的指数。 它的优点是所有位的二进制值都为零表示最小的值。 而所有位的二进制值为1表示最大值。 正如名字所表示的那样,该值以二进制编码(正值或负值),n位有偏差(通常为2 ^(n-1)或2 ^(n-1)-1)。
所以如果我们使用8位,那么十进制中的值1用2 ^(n-1)的偏差以二进制表示,其值为:
+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129 converting to binary 1000 0001
Java整数是32位,并始终签名。 这意味着,最重要的位(MSB)作为符号位。 int
表示的整数不过是比特的加权和。 权重分配如下:
Bit# Weight 31 -2^31 30 2^30 29 2^29 ... ... 2 2^2 1 2^1 0 2^0
请注意,MSB的权重为负数(实际上可能是最大的负数),所以当此位打开时,整数(加权和)变为负数。
让我们用4位数字来模拟它:
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
所以,这两个补码不是一个表示负整数的排他scheme,相反我们可以说整数的二进制表示总是相同的,我们只是否定了最重要的位的权重。 那一点决定了整数的符号。
在C中,有一个关键字unsigned
(在java中不可用),可以用来声明unsigned int x;
。 在无符号整数中,MSB的权重是正的( 2^31
),而不是负的。 在这种情况下, unsigned int
的范围是0
到2^32 - 1
,而int
范围是-2^31
到2^31 - 1
。
从另一个angular度来看,如果把x
的二进制补码看作~x + 1
(不是x加1),下面是解释:
对于任何x
,〜x只是~x
的位逆,所以当x
有1
位时,〜x将有0
位(反之亦然)。 所以,如果将这些加起来,那么在加法中就不会有任何进位,并且和将只是一个整数,每一位都是1
。
对于32位整数:
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
最左边的1
位将被丢弃,因为它不适合32位(整数溢出)。 所以,
x + ~x + 1 = 0 -x = ~x + 1
所以你可以看到,负x
可以用~x + 1
来表示,我们称之为x
的二的补码。
我运行了下面的程序来了解它
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
从输出看来,它一直在使用二进制补码。
Oracle提供了一些关于Java 数据types的文档,您可能会感兴趣。 特别:
int:int数据types是一个32位有符号的二进制补码整数。 最小值为-2,147,483,648,最大值为2,147,483,647(含)。
顺便说一句,短也存储为二进制补码。
根据这个文档 ,所有的整数都是以java的二进制补码格式进行签名和存储的。 不确定其可靠性..
最高有效位(32位)表示数字是正数或负数。 如果是0,则表示数字是正数,并以实际的二进制表示forms存储。 但是如果是1,则表示该数字是负数,并以其二进制补码表示存储。 所以当我们把第二十二位的权值-2 ^ 32从二进制表示中恢复出来的时候,我们得到了实际的答案。
谢谢你, dreamcrash的答案https://stackoverflow.com/a/13422442/1065835 ; 在维基页面上,他们给出了一个例子,帮助我理解如何找出正数的负数的二进制表示。
例如,使用1个字节(= 2个半字节= 8个比特),十进制数5表示为
0000 01012最重要的位是0,所以模式代表一个非负值。 要用二进制表示法转换为-5,这些位是相反的; 0变成1,1变成0:
1111 1010此时,数字是十进制值-5的补码。 为了得到二的补码,将1加到结果中,给出:
1111 1011结果是一个带符号的二进制数,代表二进制补码forms的十进制值-5。 最重要的位是1,所以表示的值是负的。
正数直接存储为二进制。 2的赞美是负数的要求。
例如:
15:00000000 00000000 00000000 00001111
-15:11111111 11111111 11111111 11110001
这里是有符号位的区别。
正数将按原样保存/修改。
eg) 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.
但是在2的补码(MSB位除外)之后将存储负数,MSB位将设置为1。
例如)当存储-10时
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
当检索时,它发现MSB被设置为1.所以它是否定的。 除了MSB以外,还会执行2的补码。
1-111 1110 --> 1-000 0001 + 1 --> 1-000 0010 Since MSB representing this is negative 10 --> hence -10 will be retrived.
铸件
还要注意的是,当你将int / short转换为字节时,只有最后一个字节会与最后一个字节MSB一起被考虑,
以“-130”为例,可以像下面那样存储
(MSB)1-(2's complement of)130(1000 0010) --> 1-111 1111 0111 1110
现在字节转换最后一个字节是0111 1110.(0-MSB)由于MSB表示它是+ ve值,所以它将被视为原样。 这是126.(+ ve)。
再举一个例子“130”,可能像下面那样存储
0-000 000 1000 0010 (MSB = 0)
现在字节转换最后一个字节是1000 0010。 (1 = MSB)由于MSB表示它是-ve值,所以将执行2的补码并返回负数。 所以在这种情况下,-126将被返回。
1-000 0010 -> (1's complement) -> 1-111 1101 -> (2's complement) 1-111 1101 + 1 -> 1-111 1110 -> (-)111 1110 = -126
(int)(char)(byte)-1 AND(int)(short)(byte)-1之间的差异
(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.
参考
为什么补码用来表示负数?
什么是“2的补充”?
对于正整数2,补偿值与MSB位0相同(like +14 2'complement is 01110)
。
对于只有负整数,我们正在计算2'complement值(-14= 10001+1 = 10010)
。
所以最后的答案是两个值(+ve and -ve)
仅以2'complementforms存储。