信息的表示与存储 - 整数的运算
一般而言,计算机中整数的运算与实际数学中的运算是有差别的,大部分编程语言(比如C语言、Java等)对于整数的运算都是有限制的,它只支持固定精度的运算。
无符号整数加法与乘法
无符号整数加法
对于两个由w位表示的无符号数x、y,其取值范围是在,则x+y的范围在,所以x+y的实际值可能大于2^w-1,超过了w位能表示的范围,所以必须对x+y的值进行截断,使其能够被w位所表示,截断方法为x+y mod 2^w
或x+y-2^w
。所以有可能出现x+y<x,x+y<y的情况。比如在Java中,char是16位无符号整数,则其最大值是65535,
无符号整数乘法
同样,取值范围是在,则x*y的取值范围是,最高可能需要2w位表示,超过了w位能表示的范围,所以必须对x*y的值进行截断,使其能够被w位所表示,截断方法为x*y mod 2^w
。
补码加法与乘法
补码加法
因为有符号整数的负数通常采用补码形式表示,所以减法可以表示为补码加法。对于两个由w位表示的有符号数x、y,其取值范围是在,则x+y的范围在,所以x+y的实际值可能超过了w位能表示的范围,所以必须对x+y的值进行截断,使其能够被w位所表示,因为x+y的值可能大于也可能小于,所以要根据不同的情况进行区分:
时,则x、y都是正数,产生了进位,符号位变为了1,所以其表示的实际数字为
时,则x、y都是负数,其符号位都是1,相加进位[1]0,符号位变为了0,所以其表示的实际数字为
时,在w位有符号整数表示范围之内,所以其表示的实际数字为
补码乘法
取值范围是在,则x*y的最小值是,其最大值是,同样如果要用补码来表示这个值,可能需要2w位,也需要截断。在计算补码乘法时,一般会将数据当作无符号数,计算好结果之后,将结果mod 2^w,将这个值转换为有符号数,就是所求的结果。比如-127用8为补码表示为[10000001]补,将该二进制对应的无符号数是129,所以,将其截断为8位后[0111110]=126。
移位运算
在计算机中乘法与除法的运算相对加法耗时更长,如果能够将其转换为移位运算,则会大幅度减少运算时间。在移位运算时,byte、short和char类型移位后的结果会变成int类型,对于byte、short、char和int进行移位时,规定实际移动的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是移动66次和移动2次得到的结果相同。
左移
左移就是在二进制位左边补0,高位抛弃,在数据没有溢出的情况下,左移k位意味着将数乘以2^w。如果有溢出,则根据无符号或有符号的规则,进行截断。
逻辑右移
逻辑右移就是在二进制位右边补0,低位抛弃。对于无符号数x,逻辑右移k位意味着x/2^k,而对于有符号数逻辑右移,右移一位则变成了正数。
算术右移
算术右移就是在二进制位右边补符号位(正数补0,负数补1),低位抛弃。右移一位相当于除2,右移k位相当于除以2的k次方。对于无符号数算术右移,结果是向0舍入;而对于有符号数,如果x>=0时,与无符号数相同,对于x<0,结果是向下舍入,比如-1>>1,结果还是-1
参考资料
版权声明: 本文为 InfoQ 作者【引花眠】的原创文章。
原文链接:【http://xie.infoq.cn/article/52656e0d173635ed88d640387】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论