今天要跟大家分享的小技巧是关于补码的, 这部分内容其实我已经在《C语言深处》里讲述过了,但我觉得这是一个非常重要知识点,所以再把它单独拿出来跟大家分享一下:
在计算机中数通常采用补码的形式来表示。正数和0的补码为其本身,负数的补码为其绝对值取反再加1。
10进制数 | 绝对值 | 原码(不包括符号位) | 反码(不包括符号位) | 补码(不包括符号位) | 实际补码(包括符号位) |
-3 | 3 | 000 0011 | 111 1100 | 111 1101 | 1111 1101 |
-23 | 23 | 001 0111 | 110 1000 | 110 1001 | 1110 1001 |
-127 | 127 | 111 1111 | 000 0000 | 000 0001 | 1000 0001 |
下面再来看一个非常有趣的赋值问题:
#include <stdio.h> int main(int argc, char **args) { char i = 0; short j = 129; i = j; printf("%d\n", i); return 0; }
运行结果为:
-127
结果出乎我们的意料,但却是正确的运行结果。来看一下这个赋值运算的原理:
上面例子中char i的值为-127,其补码为1000 0001正好是short j的129的原码。所以char i = 129;的结果是-127。
负数在计算机中通常以补码(反码+1)的形式表示,那为什么要采用反码+1来表示负数呢?我们来看一下9的补码为0000 1001(正数的补码是其原码)。在计算机中为了能让CPU对所有的数,无论是正数还是负数都能够快速的进行正确的加减运算,例如要让CPU能够快速的识别并运行9 + (-9) = 0这样的运算法则。也就是说让0000 1001加上一个数(-9)能让结果快速的变为0,这个过程分为两步:
1.让9加上其本身的反码,即得到一个全1的结果:
0000 1001
+ 1111 0110
1111 1111
2.在全1的结果基础上再加1,即出现多米诺骨牌效应,所有位均为0,第9个bit位的1溢出,所以结果为0:
1111 1111
+ 0000 0001
0000 0000
把上面两步的运算合并成一步运算,即一个正数加上其反码+1结果为0,为了能让CPU能够快速的计算正负数的加减法,所以负数通常采用“补码”的形式来表示。
再来看看两个负数的加法:
(-9) + (-7) = -16
-9的补码为1111 0111,-7的补码为1111 1001,两个负数的加法结果为:
1111 0111
+ 1111 1001
1111 0000
1111 0000取其补码(符号位不变)的结果为1001 0000 = -16
补码是为了便于CPU执行数的加减法运算,无论是正数还是负数CPU都可以快速识别和计算,并很好的通过多米诺骨牌效应达到正确的计算结果。
今天的小技巧你学会了吗?
Copyright © 2015-2023 问渠网 辽ICP备15013245号