您的位置:首页 > 其它

使用位运算实现加减乘除四则运算

2015-07-27 09:25 337 查看
程序员面试宝典上有这个一个题,不使用+-×/来实现加法操作,想了半天,不明白,于是乎,查找了一些资料,反复研究,总结出了四则运算的位运算来实现。

1.加法:异或操作求出没有进位的位,与运算为进位的位,然后左移一位为进位后的值。反复执行此操作,直到进位为零后,异或就为最终结果。

2.减法:减法是加法的逆运算,第二个数取相反数+1后,执行加法操作。

3.乘法:b个a相加的结果。也就是b中位为1的值左移后反复加上a。

4.除法:乘法的逆运算。a减去b,知道a为零时,迭代的次数。

下面为详细方法介绍。

^: 按位异或;&:按位与; | :按位或

计算机系统中,数值一律用补码来表示:因为补码可以使符号位和数值位统一处理,同时可以使减法按照加法来处理。

对补码做简单介绍:数值编码分为原码,反码,补码,符号位均为0正1负。

原码 -> 补码: 数值位取反加1

补码 -> 原码: 对该补码的数值位继续 取反加1

补码 的绝对值(称为真值):正数的真值就是本身,负数的真值是各位(包括符号位)取反加1(即变成原码并把符号位取反).

b -> -b : 各位(包括符号位)取反加1

加法运算:将一个整数用二进制表示,其加法运算就是:相异(^)时,本位为1,进位为0;同为1时本位为0,进位为1;同为0时,本位进位均为0.

所以,不计进位的和为sum = a^b,进位就是arr = a&b,(与sum相加时先左移一位,因为这是进位)。完成加法直到进位为0.

减法运算:a-b = a+(-b)  根据补码的特性,各位取反加1即可(注意得到的是相反数,不是该数的补码,因为符号位改变了)

(上面用二进制实现的加减法可以直接应用于负数)

乘法运算:原理上还是通过加法计算。将b个a相加,注意下面实际的代码。

除法运算:除法运算是乘法的逆。看a最多能减去多少个b,

1 #include<iostream>
2 #include<cstdlib>
3 using namespace std;
4
5 //递归版本的加法实现
6 int Add(int a, int b)
7 {
8     return b ? Add(a^b, (a&b)<<1) : a;
9     /*
10     if(b)
11         return plus_rec(a^b, (a&b)<<1);
12     else
13         return a;
14         */
15 }
16
17 //该为迭代版本
18 int Add_iter(int a, int b)
19 {
20     int ans;
21     while(b)
22     {
23         ans = a^b;
24         b = (a&b)<<1;
25         a = ans;
26     }
27     return ans;
28 }
29
30 //求a的相反数:将各位取反加一
31 int negative(int a)     //get -a
32 {
33     return Add(~a, 1);
34 }
35
36 int Minus(int a, int b)
37 {
38     return Add(a, negative(b));
39 }
40
41 //正数乘法
42 int Multi(int a, int b)
43 {
44     int ans = 0;
45     while(b)
46     {
47         if(b&1)
48             ans = Add(ans, a);
49         a = a << 1;
50         b = b >> 1;
51     }
52     return ans;
53 }
54
55 //正数除法
56 int Divide(int a, int b)
57 {
58     int coun = 0;
59     while(a >= b)
60     {
61         a = Minus(a, b);
62         coun = Add(coun, 1);
63     }
64     return coun;
65 }
66
67 //判断是否是负数,0,正数
68 int isneg(int a)
69 {
70     return a & 0x8000;
71 }
72 int iszero(int a)
73 {
74     return !(a & 0xFFFF);
75 }
76 int ispos(int a)
77 {
78     return (a&0xFFFF) && !(a&0x8000);
79 }
80
81 //处理负数的乘法和除法
82 int My_Multi(int a, int b)
83 {
84     if(iszero(a) || iszero(b))
85         return 0;
86     if(isneg(a))
87     {
88         if(isneg(b))
89             return Multi(negative(a), negative(b));
90         else
91             return negative(Multi(negative(a), b));
92     }else if(isneg(b))
93         return negative(Multi(a, negative(b)));
94     else
95         return Multi(a, b);
96 }
97
98 int My_Divide(int a, int b)
99 {
100     if(iszero(b))
101     {
102         cout << "Error!" << endl;
103         exit(1);
104     }
105     if(iszero(a))
106         return 0;
107     if(isneg(a))
108     {
109         if(isneg(b))
110             return Divide(negative(a), negative(b));
111         else
112             return negative(Divide(negative(a), b));
113     }else if(isneg(b))
114         return negative(Divide(a, negative(b)));
115     else
116         return Divide(a, b);
117
118 }
119
120 int main(int argc, char **argv)
121 {
122     int a = 5;
123     int aa = -5;
124     int b = 3;
125     int bb = -3;
126     int c = 15;
127     cout << Add(a, b) << endl;
128     cout << Add(a, bb) << endl;
129     cout << Minus(a, b) << endl;
130     cout << Minus(b, a) << endl;
131     cout << Multi(a, b) << endl;
132     cout << My_Multi(aa, b) << endl;
133     cout << Divide(c, a) << endl;
134
135     return 0;
136 }


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: