总结
1-正数的原码,反码,补码都一致;负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补
2-结论:机器数存储的是“补码”
3-为何机器不用“反码”进行运算?
为了“尝试”让符号位直接参与加减法运算,引入“反码”。但是很多结果是不对的。
3.1 符号位直接参与运算结果不对
想象一个8位数的"-1+3"运算,如果用反码计算 [11111110]反 + [00000011]反,无论符号位参参与运算,结果都很奇怪:
- 符号位参与运算: [11111110]反 + [00000011]反 = [00000001]反 = [01111110]原 不等于 2
- 符号位不参与运算:[11111110]反 + [00000011]反 = [00000001]反 = [0111111]原 不等于 2
3.2 +0 -0 的问题
用反码计算减法, 在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.
4-为何机器使用“补码”进行运算?
为了解决反码符号位计算的错误,以及+0和-0的问题,引入“补码”。
4.1 符号位直接参与运算结果正确
想象一个8位数的"-1+3"运算,如果用补码计算:
-1+3 = [11111111]补 + [00000011]补 = [0000 0010]补 = [0000 0010]原 = 2
4.2 +0 -0 的问题
这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:
-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)。
使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].
因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.
原文链接
原码,补码和反码:https://www.cnblogs.com/wqbin/p/11142873.html
为什么计算机采用补码而不是原码或反码?https://www.zhihu.com/question/352057791