一个数在计算机中是以二进制数表示形式存在的, 这个二进制数称为机器数,其值称为真值。
符号数和无符号数是针对符号出现的两种机器数表示方法。同一个二进制数,作为符号数和无符号数其真值是不同的(这里只关
注有符号数)。符号数如: char, short ,int, long等类型的变量。
定点数和浮点数是针对小数点出现的两种机器数表示方法。浮点数如:double,float
在计算机内,有符号数有3种表示法:原码、反码和补码。只有符号数才有原码, 反码, 补码
(1)原码
A:所谓原码就是二进制数的有符号表示法,即最高位为符号位,
“0”表示正,“1”表示负,其余位表示数值的大小。 以byte类型的8字节二进制举例
举例: 符号位 数值位
+7 0 0000111
-7 1 0000111
B:原码不能直接参加运算,可能会出错。例如数学上,1+(-1)=0,而在二进制中原码
00000001+10000001=10000010,换算成十进制为-2。显然出错了。
(2)反码
A:正数 与原码相同
B:负数 符号位不变,数值位按位取反,0变1,1变0。
举例: 符号位 数值位
+7 0 0000111
-7 1 1111000
(3)补码
在计算机中,数值一律用补码来表示(存储)。
主要原因:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如
果最高位(符号位)有进位,则进位被舍弃。
A:正数 与原码相同
B:负数 反码加1。
举例: 符号位 数值位
+7 0 0000111
-7 1 1111001
联系到byte类型的数据表数范围是[-128, 127],而不是最大值11111111=127,最小值01111111=-127,那么-128是怎么表示的呢
-128没有原码反码,其实是[00000000]表示正0,而0是无符号的,负0即10000000实际上就是表示的-128,它的得来方式:
(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补
-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表
示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000
0000]原, 这是不正确的)。
使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是
为什么8字节二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127]。
同理,其他几个数据类型,如short16字节表数范围 [-32768,32767 ](2的15次方),int32字节
表数范围[-2147483648,2147483647](2的31次方),也都是用所谓的负0表示最左的边界数,
同一个数字,如-128,定义成不同数据类型,其存储时的补码肯定也是不一样的。
对于正数,原码补码反码都是一致的。负数的比较麻烦一些
Integer,Long等这些包装类中,提供了
* Integer.toBinaryString(i)方法:
* 返回将该值转换为二进制补码形式的无前导 0的 ASCII 数字字符串,
* 例 7 ---> 111 ,-7 ---> 11...1001(中间28个1)