int add(int a, int b) {//加法
int sum = a ^ b; //和,100行
int carry = (a & b) << 1; //进位
while (carry) { //直到进位=0
int osum = sum;
sum = sum ^ carry; // 同样的结构再来一遍
carry = (osum & carry) << 1;
}
return sum;//没有进位了,sum就是结果
}
int sub(int a, int b) {//减法
int negate_b = add(~b, 1); //使用纯位运算实现的加法
return add(a, negate_b); //保证了减法的位运算实现性(?)
}
4.乘法,最容易想到版
那么,由于乘法是加法的简便运算,所以完全可以通过迭代来实现乘法。
思路清晰,直接coding。
int mul(int a, int b) {//乘法
int abs_a = a > 0 ? a : add(~a, 1);//保证纯位运算
int abs_b = b > 0 ? b : add(~b, 1);
int product = 0, count = 0;//已累加的次数与乘积
while (count < abs_b) {//累加a
product = add(product, abs_a);
count = add(count, 1);//同样保证纯位运算
}
//随后确定符号
if ((a ^ b) < 0) {//若a与b一正一负,则前面一堆0和1会异或成1导致结果小于0
product = add(~product, 1);//取负
}
return product;//完成
}
5.乘法,优化版
很明显,在 b 较大的情况下,上述算法即使有位运算的速度I buff加成,但是受到一个缓慢III debuff的情况下还是会很慢。
$2.$每一次检查乘数(竖式底下的数)的末位,如果是1,则在结果上加上被乘数;若是0则什么都不做。
$3.$被乘数左移一位,乘数右移一位(这是为了保证每次加的东西都对)
$4.$定号并输出
那么此时给个代码:
```java
int mul(int a, int b) {
int abs_a = a > 0 ? a : add(~a, 1);
int abs_b = b > 0 ? b : add(~b, 1);//绝对值
int product = 0;//乘积
while (abs_b > 0) {//大于0
if (abs_b & 1 > 0) {//把前面所有位清零
product = add(product, abs_a);//最后一位是1,加被乘数
}
abs_a <<= 1;
abs_b >>= 1;
}
if ((a ^ b) < 0) {//一正一负
product = add(~product, 1);
}
return product;//返回
}
```
虽然代码多了两行,但是性能有了极大提升,而且,就两行而已啊!
---
### 6.除法
那么很明显,除法也无非是多次相减而已:
```java
int div(int a, int b) {//返回商
int abs_a = a > 0 ? a : add(~a, 1);
int abs_b = b > 0 ? b : add(~b, 1);
int quotient = 0;
while (a > b) {
quotient = add(quotient, 1);//喜加一
a = sub(a, b);//a-b
}
if ((a ^ b) < 0) {
quotient = add(~quotient, 1);//取负
}
return quotient;//余数?不存在的
}
```
显然不够快。
这是因为什么呢?
小了,格局小了!
直接 $2^n$ 次方的减就好了啊!
代码:
```java
int div(int a, int b) {//返回商
int abs_a = a > 0 ? a : add(~a, 1);
int abs_b = b > 0 ? b : add(~b, 1);
int quotient = 0;
for (int i = 31; i >= 0; i--) {//只到2的31次方
if ((a >> i) >= divisor) {//能减,用右移是为了防溢出
quotient = add(quotient, 1 << i);//直接加2的i次方
a = sub(a, b << i);//当然也要减这么多了
}
}
if ((a ^ b) < 0) {//然后就是老规矩了
quotient = add(~quotient, 1);
}
return quotient;
}
```
那么现在我们就有了位运算,最后不再——
---
### 7.快速幂
——整个乘方?
代码直接照搬之前的一篇文章。
```java
int quickPow(int a, int b) {
while (b > 0) {
if (b & 1 == 1) result = mul(result, a);
b >>= 1;
a = mul(a, a);
}
return result;
}
```
---
### 8.
随着位运算五件套的给出,这篇博客也就结束了。
估计能让加减乘除快一点(?)