Java 基础

总结

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

原文地址:https://www.cnblogs.com/frankcui/p/14238776.html