我不明白为什么一个字节可以取的最小值是-128
。我可以看到最大值是127
,因为它是01111111
二进制的,但是一个怎么-128
只用8位表示,其中之一用于符号呢?正数128已经是8位,即10000000
,那么您将需要第9位来表示负号。
有人可以帮我解释一下。
我不明白为什么一个字节可以取的最小值是-128
。我可以看到最大值是127
,因为它是01111111
二进制的,但是一个怎么-128
只用8位表示,其中之一用于符号呢?正数128已经是8位,即10000000
,那么您将需要第9位来表示负号。
有人可以帮我解释一下。
short
,int
和long
。
why java byte type is not a range of 0..255
?实际上,许多人的确会问这个问题,在大多数语言中,byte
类型都是无符号的,但在Java中byte
也是带符号的,而且我(和许多其他人)认为,从一开始就在Java中保留了这种不好的设计。当您使用JNI时会遇到一些问题,当您命名为byte
0..255时请相信我!
Answers:
答案是二进制补码。
简而言之,Java(和大多数现代语言)不使用有符号大小表示来表示有符号整数。换句话说,8位整数不是符号位,后跟7位无符号整数。
相反,负整数在称为二进制补码的系统中表示,它使硬件更容易进行算术处理,并且还消除了具有正零和负零的潜在歧义。消除负零的副作用是,在范围的底部始终有一个额外的负数可用。
二进制补码系统的另一个有趣特性是,第一位有效地用作符号指示符(即,从位1开头的所有数字均为负),但接下来的七个位不能自己解释为使用符号位。
二进制补码并不是很复杂,但是初步了解二进制补码是什么,以及它如何工作以及为什么起作用,可能超出了SO答案的范围。从Wikipedia文章开始,或在google中搜索更多资源。
为了尝试简短地解决有关-128的查询,生成二进制补码背后的基本思想是采用数字的无符号形式,将所有位取反并加1。因此,无符号128是10000000。取反的是01111111,再加上一个将获得10000000。因此,在二进制补码系统中,10000000明确是-128而不是+128。大于或等于+128的数字根本无法使用二进制补码系统以8位表示,因为它们会与负数形式产生歧义。
补码的工作原理如下:
一个字节由8位组成。
00000000表示0
11111111表示255
但是,如果以这样的方式显示数字,则我们将不会区分结果数字是正数还是负数。由于这个原因,左侧的位为我们提供了此信息。如果左侧的位为0
,则可以开始在的顶部添加其他位的值zero
。如果是位1
,则应在的顶部开始添加-128
。因为左侧的位是2到7的幂。
例子;
在这些示例中,左侧的位为1,这意味着我们要在-128的顶部添加其他位的值。
10000000 = -128(-128 + 0)
10000001 = -127(-128 +1)
10000011 = -125(-128 + 3)
10000111 = -121(-128 + 7)
相同的位,但是这次,左边的位是0
。这意味着我们开始在的顶部添加0
。
00000000 = 0(0 + 0)
00000001 = 1(0 +1)
00000011 = 3(0 + 3)
00000111 = 7(0 + 7)
如果到目前为止还可以,请回答您的问题,
最小的数字
10000000 = -128
可能的最大数量
011111111 = 127
这就是为什么范围在-128到127之间的原因。
字节由8位组成---> 1位符号(正或负)7位值
因此范围-2 ^ 7负(-128)至2 ^ 7 -1正(127)
在Java中,所有变量(如byte short int long float float double)均按有符号形式编写。因此,非常简单的是,首位始终指定什么(负数或正数),但是由于数字可除以2的一半被移位为负数,因此默认情况下0为正数。所以看起来像这样:
这是正
+ | 0001001
1 | 0001001
这是负
-| 0001001
0 | 0001001,
因为一个字节短,负为
-000000011111111
0000000011111111
无需取二进制补码:2 ^ 8(因为一个字节是8位数字,并且可以具有2个值中的1个)= 256,所以一个字节可以代表的最单独的值是256。因此,表示数字-128到-1是我们范围的一半。我相信这里的问题是为什么最大正值是127,而不是128。这是因为我们必须表示数字0,所以0-127是我们范围内的其他128个可能性。
如果我们只允许使用正值,例如不可能使用负数的无符号字节,则范围将是0-255,因为它们是256个不同的值(包括0)。