初识C语⾔之原码、反码、补码的理解
⽂章⽬录
前⾔
负数二进制补码运算法则本⽂为C语⾔初学者对原码、反码、补码的学习笔记。理解略浅。
⼀、原码、反码、补码的概念
原码就是符号位加上真值的绝对值,最⾼位为符号位,其余为表⽰值。正数的原码反码补码都是其本⾝,你可认为正数原码就是反码或者补码。负数的补码符号位不变,其余按位取反。补码等于反码加1,原码符号位不变其余按位取反后加1为反码。
⼆、原码、反码、补码的计算
1.原码
原码就是符号位加上真值的绝对值,⽤最⾼位(第⼀位)表⽰符号位,其余表⽰值,⽰例:如果是8位⼆进制:
[+1] = [00000001]
[-1] = [10000001]
第⼀位是符号位,因为第⼀位是符号位,所以8位⼆进制的取值范围是:
[+1]的取值范围为:[01111111] 即 [+127]
[-1] 的取值范围为:[11111111] 即 [ -127]
2.反码
正数的反码是其本⾝,你可以认为它即是原码⼜是反码。负数的反码是在其原码的基础上符号位不变,其余位按位取反。⽰例:如果是8位⼆进制:
[+1] = 原码: [00000001] = 反码: [00000001]
[-1] = 原码: [10000001] = 反码: [11111110]
3.补码
正数的补码就是其本⾝,你即可以认为它就是补码⼜可以认为是原码或反码,负数的补码就是,在其原码的基础上,符号位不变,其余按位取反后 +1。⽰例:如果是8位⼆进制
[+1] = 原码: [00000001] = 反码: [00000001] = 补码: [00000001]
[-1] = 原码: [10000001] = 反码: [11111110] = 补码: [11111111]
⽽计算机在内存中存储⽅式就是补码
总结
既然有了原码为什么还要⽤反码和补码?
⼈可以⼀知道第⼀位是符号位,在计算机的时候我们会根据符号位对真值区域的加减,但是对于计算机加减乘除已经是最基本运算,计算机考虑符号位显然让计算机基本电路设计会变得⼗分复杂。于是⼈们想出了符号位也加⼊运算,根据运算法则减去⼀个正数等于加上⼀个负数,如:1 - 1 = 1 + (-1) = 0; 所以计算机只有加法没有减法。这让计算机的运算更简单。
所以符号位也加⼊运算的话⽤原码反码补码的实现是这样的:
原码:
1 + (-1) = 原码[00000001] + 原码[10000001] = [10000010] = -2
显然这样算出来是不正确的。这就是为何计算机内部不使⽤原码表⽰⼀个数。
为了解决原码做减法的问题出现了反码,反码实现是这样的:
反码:
1 + (-1) = 反码[00000001] + 反码[11111110] = 反码[11111111] = 原码[10000000] = -0
这样计算真值不是正确的,唯⼀的问题就出现在 0 的时候,虽然都知道 -0和+0 都是 0,但是带符号是没有任何意义的,⽽且会有[00000000] (原码) 和 [10000000] (原码) 两个编码表⽰ 0。于是补码出现,解决了0的符号和两个编码问题。
补码:
1 + (-1) = 补码[00000001] + 补码[11111111] = 补码[00000000] = 原码[00000000] = 0
1 + (-2) = 补码[00000001] + 补码[11111101] = 补码[11111110] = 原码[10000001] = -1
0 = [00000000]这样之前的-0就被解决了,⽽且可以⽤[10000000]可以表⽰-128
-1 + (-127) = 原码[10000001] + 原码[11111111] = 补码[11111111] + 补码[10000001] = 补码[10000000] = -128
但是实际上-128⽤的是原来的-0,所以-128没有原码和反码表⽰,-128 补码[10000000]算出来的原码是[00000000]。很明显这是不正确的。
使⽤补码不仅解决 -0 和两个编码的问题,⽽且能多表⽰⼀个最低数,这就是为什么8位⼆进制的原码和反码表⽰的范围 [-127, 127]。⽽补码表⽰的范围 [-128, 127]

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。