首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在Java中,整数是如何在内部以位级别表示的?

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

Stack Overflow用户
提问于 2012-11-17 02:22:41
回答 10查看 79.3K关注 0票数 86

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

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

我看到说明书上写着x bit two's complement number。但我经常感到困惑。

例如:

代码语言:javascript
复制
  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

代码语言:javascript
复制
   In binary as is: `00000000 00000000 00000000 00001111'
  Two's complement: `11111111 11111111 11111111 11110001`

因此,如果您的答案是all数字被存储为2的补码,那么:

代码语言:javascript
复制
  int x = 15; // 11111111 11111111 11111111 11110001
  int y = -22 // 11111111 11111111 11111111 11101010

这里同样令人困惑的是,标牌上写着,两者都是负数。可能是我读错了/误解了?

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

准确地说,我的问题是:正数是否存储在binary as is two's complement**?**中,而负数是否存储为

有些人说所有的都存储在二的补码中,一个答案说只有负数才存储为二的补码。

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2012-11-17 02:36:49

让我们首先总结一下Java基本数据类型:

Byte :Byte数据类型是一个8位有符号二进制补码整数

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

Int : Int数据类型是32位有符号二进制补码整数

Long : Long数据类型是64位有符号二进制补码整数

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

double :double data type是一种双精度64位IEEE754浮点

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

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

Source

2的补码

wiki中的一个很好的例子是,通过注意256 = 255 + 1,并且(255−x)是x的1的补码,实现了与2的补码的关系

0000 0111=7的二进制补码是1111 1001= -7

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

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

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

负整数存储为2的绝对值的补码。当使用这种记法时,两个正数的补码就是负数。

Source

因为这个答案我得到了几分,所以我决定给它添加更多的信息。

更详细的答案:

在其他方法中,有四种主要方法来表示二进制中的正数和负数,即:

签名Magnitude

  • One's Complement

  • Two's Complement

  • Bias

1.带符号幅度

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

代码语言:javascript
复制
1011 = -3
0011 = +3

这种表示更简单。但是,您不能以添加十进制数的相同方式添加二进制数,这使得在硬件级别上实现变得更加困难。此外,该方法使用两种二进制模式来表示0,即-0 (1000)和+0 (0000)。

2.一个人的互补

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

代码语言:javascript
复制
010 = 2, so -2 = 101 (inverting all bits).

这种表示的问题在于仍然存在两个位模式来表示0,负0 (1111)和正0 (0000)

3.二进制补码

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

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

代码语言:javascript
复制
4 = 0100

然后我们反转所有的比特

代码语言:javascript
复制
0100 -> 1011

最后,我们添加一位

代码语言:javascript
复制
1011 + 1 = 1100.

因此,如果我们使用具有4位的二进制补码表示法,1100相当于十进制中的-4。

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

代码语言:javascript
复制
0100 -> 1100
^^ 
||-(fixing this value)
|--(inverting this one)

二的补码表示法,除了0只有一个表示法外,它还以与十进制相同的方式将两个二进制值相加,即具有不同符号的偶数。尽管如此,还是有必要检查溢出情况。

4.偏置

此表示法用于表示浮点的IEEE754规范中的指数。它的优点是,所有位都为零的二进制值表示最小值。并且所有位都为1的二进制值表示最大值。顾名思义,该值以带有偏置的n位(通常为2^(n-1)或2^(n-1)-1)的二进制形式进行编码(正或负)。

因此,如果我们使用8位,十进制值1用二进制表示,偏置为2^(n-1),值为:

代码语言:javascript
复制
+1 + bias = +1 + 2^(8-1) = 1 + 128 = 129
converting to binary
1000 0001
票数 111
EN

Stack Overflow用户

发布于 2012-11-17 02:39:46

Java整数是32位的,并且总是有符号的。这意味着,最高有效位(MSB)用作符号位。由int表示的整数只不过是位的加权和。按如下方式指定权重:

代码语言:javascript
复制
Bit#    Weight
31      -2^31
30       2^30
29       2^29
...      ...
2        2^2
1        2^1
0        2^0

请注意,MSB的权重为负数(实际上可能是最大的负数),因此此位为on时,整数(加权和)为负数。

让我们用4位数字来模拟它:

代码语言:javascript
复制
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

因此,二进制补码并不是表示负整数的排他性方案,相反,我们可以说整数的二进制表示总是相同的,我们只是否定了最高有效位的权重。该位决定了整数的符号。

在C中,有一个关键字unsigned (在java中不可用),可以用来声明unsigned int x;。在无符号整数中,MSB的权重是正的(2^31),而不是负的。在这种情况下,unsigned int的范围是02^32 - 1,而int的范围是-2^312^31 - 1

从另一个角度来看,如果您认为x的两个补码是~x + 1 (而不是x加1),那么可以这样解释:

对于任何x~x只是x的逐位逆,所以无论x在哪里有1-bit,~x都会在那里有一个0-bit (反之亦然)。所以,如果你把这些加起来,在加法中不会有进位,和只是一个整数,它的每一位都是1

对于32位整数:

代码语言:javascript
复制
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-bit将被简单地丢弃,因为它不适合32位(整数溢出)。所以,

代码语言:javascript
复制
x + ~x + 1 = 0
-x = ~x + 1

所以你可以看到负的x可以用~x + 1来表示,我们称之为x的2的补码。

票数 62
EN

Stack Overflow用户

发布于 2012-11-17 02:36:37

我已经运行了下面的程序来了解它

代码语言:javascript
复制
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));
    }
}

输出为

代码语言:javascript
复制
1010
11111111111111111111111111110110

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

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13422259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档