原码、补码、反码及计算机中负数的表示

来源:互联网 发布:js round 编辑:程序博客网 时间:2024/04/30 02:01

原码

第一位为符号位,后面的为数字的二进制表示。

eg: 127 和 -127 的 8位原码为 [0111 1111, 1111 1111]

反码

正数的反码为其原码;负数的反码,符号位不変,后面的取反。

eg: 1的8位原码和反码为 [00000001]原 = [00000001]反
-1的8位反码为 [10000001]原 = [11111110]反

补码

正数的反码为其原码;负数的补码为其补码+1

[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补

为什么用补码

将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

然而,如果使用原码运算:

计算十进制的表达式: 1-1=0
1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

结果不正确,如果用反码的话:

1-1=0
1 - 1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]反 + [1111 1110]反
= [1111 1111]反
= [1000 0000]原
= -0

结果的真值部分是正确的. 而唯一的问题其实就出现在”0”这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]补 + [1111 1111]补
= [0000 0000]补
=[0000 0000]原

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127)
= [1000 0001]原 + [1111 1111]原
= [1111 1111]补 + [1000 0001]补
= [1000 0000]补

INT_MAX & INT_MIN

这就是为什么C++ 中 INT_MAX 是2147483647 , 而INT_MIN是 -2147483648

#define INT_MAX 2147483647  #define INT_MIN (-INT_MAX - 1) 

这里没有简单地将INT_MIN赋值成 -2147483648,是因为-2147483648对于编译器而言是个表达式,而2147483648对于32-bit整数是无法表示的,在计算机中以原码的形式表示为 10000…0000(31个0)。

Reference

http://blog.csdn.net/u011080472/article/details/51280919
http://blog.csdn.net/seizef/article/details/7605010

0 0
原创粉丝点击