编程语言
首页 > 编程语言> > C++ 补码详解

C++ 补码详解

作者:互联网

文章目录

一、引例

	printf("%d\n", abs(INT_MIN));

-2147483648

二、机器数和真值

1、机器数

2、真值

三、计算机编码

1、原码

【原码定义】 符号位为 0 代表正数,符号位为 1 代表负数,数值位为真值的绝对值。

[ x ] 原 = { x ( 0 < = x < 2 n − 1 ) 2 n − 1 − x ( − 2 n − 1 < x < = 0 ) [x]_原 = \begin{cases} x & (0 <= x < 2^{n-1})\\ 2^{n-1} - x & (-2^{n-1} < x <= 0)\\ \end{cases} [x]原​={x2n−1−x​(0<=x<2n−1)(−2n−1<x<=0)​
(这里 n n n 的取值是 8 、 16 、 32 、 64 8、16、32、64 8、16、32、64,目前计算机的整型 int 都是 32 位的,但是为了便于阅读,本文介绍的整数都按照 8 位来举例)

【原码举例】

2、补码

【补码定义】 正数的补码是它本身,符号位为0;负数的补码为原码数值位取反后+1,符号位为1;
[ x ] 补 = { x ( 0 < = x < 2 n − 1 ) 2 n + x ( − 2 n − 1 < = x < 0 ) [x]_补 = \begin{cases} x & (0 <= x < 2^{n-1})\\ 2^{n} + x & (-2^{n-1} <= x < 0)\\ \end{cases} [x]补​={x2n+x​(0<=x<2n−1)(−2n−1<=x<0)​
【补码举例】

(尝试把负数的数值部分和它的补码进行相加运算,可以得到 2 n 2^n 2n)

3、反码

【反码定义】 整数的反码是它本身,符号位为0;负数的反码为原码数值取反,符号位为1;
[ x ] 反 = { x ( 0 < = x < 2 n − 1 ) 2 n − 1 + x ( − 2 n − 1 < x < = 0 ) [x]_反 = \begin{cases} x & (0 <= x < 2^{n-1})\\ 2^{n}-1 + x & (-2^{n-1} < x <= 0)\\ \end{cases} [x]反​={x2n−1+x​(0<=x<2n−1)(−2n−1<x<=0)​
【反码举例】

(尝试把负数的数值部分和它的补码进行相加运算,可以得到 2 n − 1 2^n-1 2n−1)

4、编码总结

[ + 1 ] = [ 00000001 ] 原 = [ 00000001 ] 反 = [ 00000001 ] 补 [+1] = [00000001]_原 = [00000001]_反 = [00000001]_补 [+1]=[00000001]原​=[00000001]反​=[00000001]补​

[ − 1 ] = [ 10000001 ] 原 = [ 11111110 ] 反 = [ 11111111 ] 补 [-1] = [10000001]原 = [11111110]反 = [11111111]补 [−1]=[10000001]原=[11111110]反=[11111111]补

四、为什么要用补码

1、主要目的

2、原码运算

1 + 1 = [ 00000001 ] 原 + [ 00000001 ] 原 = [ 00000010 ] 原 1 + 1 = [00000001]_原 + [00000001]_原 = [00000010]_原 1+1=[00000001]原​+[00000001]原​=[00000010]原​ = 2

1 − 2 = 1 + ( − 2 ) = [ 00000001 ] 原 + [ 10000010 ] 原 = [ 10000011 ] 原 1 - 2 = 1 + (-2) = [00000001]_原 + [10000010]_原 = [10000011]_原 1−2=1+(−2)=[00000001]原​+[10000010]原​=[10000011]原​ = -3

3、反码运算

1 − 2 = 1 + ( − 2 ) = [ 00000001 ] 反 + [ 11111101 ] 反 = [ 11111110 ] 反 1 - 2 = 1 + (-2) = [00000001]_反 + [11111101]_反 = [11111110]_反 1−2=1+(−2)=[00000001]反​+[11111101]反​=[11111110]反​ = -1

1 − 1 = 1 + ( − 1 ) = [ 00000001 ] 反 + [ 11111110 ] 反 = [ 11111111 ] 反 1 - 1 = 1 + (-1) = [00000001]_反 + [11111110]_反 = [11111111]_反 1−1=1+(−1)=[00000001]反​+[11111110]反​=[11111111]反​ = -0

4、补码运算

1 − 2 = 1 + ( − 2 ) = [ 00000001 ] 补 + [ 11111110 ] 补 = [ 11111111 ] 补 1 - 2 = 1 + (-2) = [00000001]_补 + [11111110]_补 = [11111111]_补 1−2=1+(−2)=[00000001]补​+[11111110]补​=[11111111]补​ = -1

1 − 1 = 1 + ( − 1 ) = [ 00000001 ] 补 + [ 11111111 ] 补 = [ 00000000 ] 补 1 - 1 = 1 + (-1) = [00000001]_补 + [11111111]_补 = [00000000]_补 1−1=1+(−1)=[00000001]补​+[11111111]补​=[00000000]补​ = 0

两个互为相反数的数相加后,得到的数的补码为 2 n 2^n 2n(你可以认为是是溢出了),和我们之前提到的定义吻合;

五、回到原点

2 31 − 2 31 = 2 31 + ( − 2 31 ) = X + [ − 2 31 ] 补 = 0 2^{31} - 2^{31} = 2^{31} + (- 2^{31}) = X + [-2^{31}]_补 = 0 231−231=231+(−231)=X+[−231]补​=0

解这个简单方程得到 X X X 唯一的值为:
[ 10000000    00000000    00000000    00000000 ] 补 [10000000\ \ 00000000\ \ 00000000\ \ 00000000]_补 [10000000  00000000  00000000  00000000]补​

标签:反码,00000000,00000001,31,补码,C++,详解,原码
来源: https://blog.51cto.com/u_15239535/2836973