前言
在上一篇中,我们介绍了使用位运算实现加法和减法运算,接下来本文主要介绍如何用位运算实现乘法运算,在实现乘法时要用位运算实现,并且不能出现加减乘除任何符号。
之前介绍过一篇如何用位运算实现加法和减法: 如何用位运算实现加减运算?
正文
在用位运算实现之前,我们先来回忆一下小学时,学乘法时用的十字相乘法。
十进制相乘
例如, 26 * 15 ,在进行乘法操作时,我们一般这样算,先用 5 乘以 6 得到 30 ,把 0 写下把 3 记在一边,再用 5 乘以 2 得到 10 再加上之前的 3 写在下面,得到 130 ;计算完 5 再计算 1 分别乘以 6 和 2 把得到的结果 26 记在下面,然后把 130 和 26 相加(有错位)得到 390 。
二进制相乘
看完了十进制的相乘,再来看下二进制的相乘,基本原理是一样的,也是以十字相乘法为例,计算 5 * 7 。
5 的二进制为 101 , 7 的二进制为 111 ,来看下二进制的十字相乘法。
可以看到二进制为 101 和二进制 111 用传统的方式来计算,得到的结果为 100011 ,而二进制 100011 对应的十进制为 35 。
所以说,在计算的过程中,十进制和二进制的计算方式是一样的,当然这里就不进行举例和证明了。
思路分析
既然计算过程有了,那么怎么样用代码来实现呢?
我们再来看下上图中二进制的计算过程:
先用二进制 111 的最后一位 1 乘上 101 得到 101 。 再用二进制 111 的倒数第2位 1 乘上 101 得到 101 。 再用二进制 111 的倒数第3位 1 乘上 101 得到 101 。 得到的三个 101 进行二进制相加,得到 100011 。注意,第 2 步和第 3 步得到的结果 101 都往前挪了一位,相当于 1010 和 10100 ,也就是最后相加的计算为: 10100 + 1010 + 101 = 100011 。
再来看得到最终相加的计算 10100 + 1010 + 101 = 100011 ,也就是只要我们找到如何把数据转换为几位数的相加就可以了,因为之前已经实现了 如何用位运算实现加法操作 。
这三个数 101 、 1010 、 10100 的数量刚好与二进制 111 的个数相同,也就是二进制(上图下面那个乘数 111 )有几位就会产生几个数相加,如果是与 11111 相乘就会产生 5 个数相加。
再来看数据之前的关系:
第一次相乘结果: 101 = 101 + 0 第二次相乘结果: 1111 = 101 < 1 + 101 = 1010 + 101 第三次相乘结果: 100011 = 101 < 2 + 1111 = 10100 + 1010 + 101从这里我们可以看到,每计算一次, 101 只需要向左移一次再加上上一次的计算结果就可以了。
那么,怎么知道要左移多少次呢?从这里例子中看, 111 每次计算后,向右移动一次, 101 也跟着向左移动一次,直到 111 只剩最后一位,则停止计算就好了。
代码实现
根据上面的思路,来实现一下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 用位运算实现加法
public static int add( int a, int b) {
int sum = 0 ;
while (b != 0 ) {
sum = a ^ b;
b = (a & b) << 1 ;
a = sum;
}
return sum;
}
// 用位运算实现减法
public static int multi( int a, int b) {
int res = 0 ;
while (b != 0 ) {
if ((b & 1 ) != 0 ) {
res = add(res, a);
}
a <<= 1 ;
b >>>= 1 ;
}
return res;
}
运行一下代码,看下结果:
可以看到计算是正确的,而且还支持负数。
总结
本文介绍了如何用纯位运算实现乘法的运算,并介绍了实现思路以及分析,需要注意的是,位运算右移的时候需要使用无符号右移,否则的话,会出现死循环的。
另外,本文只是介绍利用位运算来实现乘法的实现过程、知识点的介绍,虽然是使用的位运算但是效率是不能和 Java 原生的加法运算相比的,并没有原生的效率高。
到此这篇关于Java利用位运算实现乘法运算详解的文章就介绍到这了,更多相关Java位运算实现乘法运算内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
原文链接:https://juejin.cn/post/7221113101591445565
查看更多关于Java利用位运算实现乘法运算详解的详细内容...