整数在计算机中是以二进制形式存储的,整数的运算归根到底是二进制位的逻辑运算。
那么如何用最基本的位运算来实现整数的四则运算?
我今天写了“加”、“减”、“乘”、“除”、“取余”和“取相反数”这几种基本运算,代码中只用到了位运算。
我选择的是short型数值,并用代码循环了所有可能的情况(两个操作数分别从-32768到32767),可以验证我的运算函数的结果和直接做运算的结果是完全相同的(包括溢出的情况)。这些函数经过简单修改很容易支持更多位的整数。
有符号整数右移操作会复制符号位,我把一些函数的参数设置成了unsigned类型的,但是调用函数的时候可以直接传进有符号数。“加”、“减”、“乘”函数传进无符号数也可以得到正确结果。
由于有符号数中负数比正数多一个-32768,所以为了让程序支持边界条件,除法运算中所有操作都是针对负数进行的。
下面附代码:
short ADD(register unsigned short a,register unsigned short b){ register unsigned short t; do{ t=a&b; a^=b; b=t<<1; }while(t); return a; } short MINUS(register unsigned short a){ return ADD(~a,1); } short SUB(register unsigned short a,register unsigned short b){ return ADD(a,MINUS(b)); } short MUL(register unsigned short a,register unsigned short b){ register unsigned short r=0; while(a){ if(a&1)r=ADD(r,b); a>>=1; b<<=1; } return r; } short DIV(register short a,register short b){ register short r=0; register char t=0; register char s=(unsigned short)(a^b)>>15; if(b==0)exit(-1); if(a>0)a=MINUS(a); if(b>0)b=MINUS(b); while(a<=(b<<t))t++; while(a<=b){ while(a>(b<<t))t--; a=SUB(a,(b<<t)); r|=1<<t; } return s?MINUS(r):r; } short MOD(register short a,register short b){ return SUB(a,MUL(DIV(a,b),b)); }
踩一踩。如果方便的话 能不能把我的blog放到友情链接里?
已经放进去了
这篇文章很赞!
你给的加法是 O(n) 的复杂度,其中 n 是二进制位数。事实上可以用 O(log n) 时间算出来,现代 CPU 里加法器就是用 Kogge–Stone adder 的原理造的。
http://en.wikipedia.org/wiki/Kogge%E2%80%93Stone_adder
代码
http://www.quora.com/How-would-you-add-two-integers-using-bit-manipulation?
如果你对位运算的奇技淫巧感兴趣,Hacker’s Delight 这本书一定不会让你失望:
http://www.hackersdelight.org/
超前进位加法器。。。
位运算完成工作的方法可以理解为CPU的工作方式。。