原码,反码,补码总结

原码就是符号位加上真值,在java中,我们知道short占用了2字节,也就是16bit。

但是我们知道它只能表示最大的正数是32767,也就是2^15-1,本来16bit可以表示的正数范围应该是

0~1111 1111 1111 1111

但是现在正数只用了一半的空间,高位数的一半被用来表示负数,最高位代表符号位,1代表负数。所以short最小数可以表示-32768也就是全是1的情况。

计算机中负数是以补码的形式存在,而反码的出现就是因为补码引起的。因为正数的反码就是本身,负数反码就是符号位不变,其余取反。

这里假设最大正数不是32767(图计算方便),假设某个类型只用4bit表示,那么它的范围就是-8到7

仔细一个个数

0000 代表 0

0001 代表 1

0010 代表 2

0011 代表 3

0100 代表 4

0101 代表 5

0110 代表 6

0111 代表 7

然后1000代表什么呢?它代表-8

1000 代表 -8

1001 代表 -7

1010 代表 -6

1111 代表 -1

本来负数的补码就是反码+1,反过来已知补码求原码就是-1,再取反。比如:

1001减1后:1000

1000取反:1111就是-7所以没问题。

但是为什么1000代表-8呢?

其实可以从同余定理的角度来理解。要表示一个负数,就用这个负数的同余数来表示。

所以可以看到

8和-8同余

9和-7同余

15和-1同余

为什么这些分别两数同余呢就是同余定理的问题了。

可以看下java代码求mod

1
2
3
	int i=Math.floorMod(-7, 16);
System.out.println(i);
//output:9

这里想,为什么是除以16?因为你长度就是16,如果你换成17,那output:10就变成了-7用10表示。

-8用9表示,-9用8表示,-10用7表示。此时等等。感觉不对吧,-10用7表示,那7用啥表示?

所以为什么不是除以15也是同样道理。

小结

到此为止,可以知道一些类型,举例short这个16bit表示的范围是32767到-32768的原因,和负数用同余数的映射关系。那么为什么负数要用补码(也就是同余数)来存?

计算机为什么负数要以补码的形式存在?

参考

因为电路计算中,借位电路比较复杂 。

有一道运算

14-7化成二进制减法 1110-0111

这里发现是不是需要借位

那么如果看成

14+(-7) 并且-7用它的同余数(补码表示)

变成1110+1001得到=0111(最高位溢出)

很神奇,答案竟然一样。所以加法电路简单,用同余数表示不需要借位运算。

总结

不必去背诵什么正数的原码反码补码一样,什么负数的补码等于反码加1而是要真正理解计算机中,为什么要出现补码,为了运算更快。负数在内存中的表示方式。