计算机系统中的整数运算
上一篇随笔中介绍了“计算机系统内的整数表示”,本文继续探索整数运算的本质。
计算机系统内的整数运算的局限:
表示整数的二进制位是一定的,所以表示的整数的范围是局限的。
“整数”运算实际上是一种模运算:
表示数字的有限字长限制了可能的取值范围,结果运算可能溢出,所以运算结果都是取模之后的。
无符号加法
一个算术运算溢出,是指完整的整数结果不能放到数据类型的字长限制中去。
C语言中真正执行的无符号加法:
+uw (用这种符号区别标准的加法; + 表示标准的加法),又称为 模数加法。
![](http://images0.cnblogs.com/blog/390993/201304/03140806-05992c602f1143bc8b3cf74a6fa28b2d.png)
= (x+y)mod 2^w
整数加法和无符号加法间的关系。当x+y大于2w-1时,其和溢出。
例如:(231 = 2147483648)
unsigned int u1=2147483648u+2147483647u; printf("u1=%u\n",u1); unsigned int u2=2147483648u+2147483647u+1; printf("u2=%u\n",u2);
输出:u1=4294967295
u2=0
补码加法
在计算机计算中,通常将表示截断到w位,来避免数据大小的不断扩张。C语言中真正执行的补码加法:+tw(用这种符号区别标准的加法)
整数和补码加法之间的关系:
当x+y小于-2w-1,产生负溢出。当它大于2w-1 -1时,产生正溢出。
例如:(int类型的最大正数为:231-1 = 2147483647)
int y=2147483647+1; printf("y=%d",y);
输出:y=-2147483648
补码的非运算
无符号乘法
其中 x*y指实数内的乘法。
有符号乘法
乘以常数
对于无符号和有符号变量x:C表达式 x<<k 等价于 x*2^k。 (左移运算)
(可以理解为:这是对二进制表示的运算,无符号和有符号是对二进制表示的两种解释)
例如:14=2^3+2^2+2 所以 x*14=(x<<3)+(x<<2)+(x<<1)
或14=2^4-2 所以 x*14=(x<<4)-(x<<1)
-6=2-8 所以 x*(-6)=(x<<1)-(x<<3)
除以2的幂
整数除法总是舍入到零,对于x>=0,y>0 ,结果是![]()
(下取整),对于x<0,y>0,结果是![]()
(上取整)
![](http://images0.cnblogs.com/blog/390993/201304/03143946-e900e5f0ce484d60b2e7edb68cf4c8e8.png)
![](http://images0.cnblogs.com/blog/390993/201304/03144000-49d4e9ed8245489583ce28e17100b171.png)
对于无符号变量x:C表达式x/2^k等价于x>>k。(逻辑右移)
对于有符号变量(补码)x:表达式x/2^k等价于(x<0 ? (x + (1<<k) -1) : x ) >>k。(算术右移)
(当x<0时,x上加上一个适当的偏移量(2^k-1),再执行算术右移,使结果正确舍入)
(转载请注明出处 ^.^)