最近复习c++,发现原码反码补码以及数据类型的表示范围这方面的概念很模糊,现整理如下,供大家参考。
1、原码:
最高位表示数的符号,其他位表示数值
例如:[+7]原 = 0000 0111 [-7]原 = 1000 0111
2、反码:
正数的反码与原码相同
例如:[+7]反 = 0000 0111
负数的反码是由原码的符号位不变,其余为按位取反
例如:[-7]反 = 1111 1000
3、补码
正数的补码与原码相同
例如:[+7]补 = 0000 0111
负数的补码是由其反码的基础上加一
例如:[-7]补 = [-7]反 + 1 = 1111 1000 +1 = 1111 1001
4、反码和补码的产生原因(顺带解释了byte型数据的表示范围为什么是-128~127)
实际上,计算机对于正数的存储方式就是二进制本身,而反码和补码的出现,是计算机为了简化和方便处理,才将负数用补码的形式存储,为什么这样说呢?请看下面的解释:
首先我们来看下计算机怎么做减法:
为了减少成本,计算机采用的用加法来代替减法,思路如下:
以时钟表盘为例,要想将时针从从3点拨到5点,有两种解决方案:
1)将时针顺时针转动2小时 3 + 2 = 5
2)将时针逆时针转动10小时 3 - 10 = 5
可以将钟表盘理解为一个模12的循环,即走完12个小时后又会走回原点
同理,对于数据类型也是如此,以byte(8位)类型为例,从 0000 0000~1111 1111是一个模256(2^8)的循环,即1111 1111加一之后又会回到0000 0000
类比钟表,我们可以将减法转换为加法,例如 3 - 2 = 3 + 254 = 256 + 1 = 1(结果正确)
但是我们思考下会发现,这样转换的减法得到的结果都是正数,如果是计算 2 - 3,过程则是:2 - 3 = 2 + 253 = 255(显然不对)
那么怎么解决呢?于是先辈们决定将255(二进制为[1111 1111])定义为 -1(即1111 1111 定义为 1000 0001对应的补码),而不是255,同理,[1111 1110]不再是254,定为-2。类推下去,0-128=0+(256-128)=128(二进制为[1000 0000]),把[1000 0000]让位给-128
也就是说,在0000 0000~1111 1111中,前一部分也就是0000 0000 ~0111 1111表示的数值大小保持不变,而后一部分1000 0000 ~1111 1111依次让位给-128 ~-1,表达的则是负数,结合前面反码和补码的定义,我们也就能够明白补码和反码的产生原因了,其实就是方便将减法转换为加法,同时,前面叙述已经能够得到byte类型的范围是-128 ~127