Java利用位运算实现乘法运算详解

 更新时间:2023年04月13日 11:24:47   作者:Java星辰  
这篇文章主要为大家详细介绍了Java如何用位运算实现乘法运算,在实现乘法时要用位运算实现,并且不能出现加减乘除任何符号,感兴趣的可以了解一下

前言

在上一篇中,我们介绍了使用位运算实现加法和减法运算,接下来本文主要介绍如何用位运算实现乘法运算,在实现乘法时要用位运算实现,并且不能出现加减乘除任何符号。

之前介绍过一篇如何用位运算实现加法和减法: 如何用位运算实现加减运算?

正文

在用位运算实现之前,我们先来回忆一下小学时,学乘法时用的十字相乘法。

十进制相乘

例如,26 * 15,在进行乘法操作时,我们一般这样算,先用5乘以6得到30,把0写下把3记在一边,再用5乘以2得到10再加上之前的3写在下面,得到130;计算完5再计算1分别乘以62把得到的结果26记在下面,然后把13026相加(有错位)得到390

二进制相乘

看完了十进制的相乘,再来看下二进制的相乘,基本原理是一样的,也是以十字相乘法为例,计算 5 * 7

5的二进制为1017的二进制为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都往前挪了一位,相当于101010100,也就是最后相加的计算为:10100 + 1010 + 101 = 100011

再来看得到最终相加的计算10100 + 1010 + 101 = 100011,也就是只要我们找到如何把数据转换为几位数的相加就可以了,因为之前已经实现了如何用位运算实现加法操作

这三个数101101010100的数量刚好与二进制111的个数相同,也就是二进制(上图下面那个乘数111)有几位就会产生几个数相加,如果是与11111相乘就会产生5个数相加。

再来看数据之前的关系:

  • 第一次相乘结果:101 = 101 + 0
  • 第二次相乘结果:1111 = 101 < 1 + 101 = 1010 + 101
  • 第三次相乘结果:100011 = 101 < 2 + 1111 = 10100 + 1010 + 101

从这里我们可以看到,每计算一次,101只需要向左移一次再加上上一次的计算结果就可以了。

那么,怎么知道要左移多少次呢?从这里例子中看,111每次计算后,向右移动一次,101也跟着向左移动一次,直到111只剩最后一位,则停止计算就好了。

代码实现

根据上面的思路,来实现一下代码:

// 用位运算实现加法
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位运算实现乘法运算内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot登录拦截器+ThreadLocal实现用户信息存储的实例代码

    springboot登录拦截器+ThreadLocal实现用户信息存储的实例代码

    ThreadLocal 为变量在每个线程中创建了一个副本,这样每个线程都可以访问自己内部的副本变量,这篇文章主要介绍了springboot登录拦截器+ThreadLocal实现用户信息存储的实例代码,需要的朋友可以参考下
    2024-03-03
  • SpringBoot整合redis+Aop防止重复提交的实现

    SpringBoot整合redis+Aop防止重复提交的实现

    Spring Boot通过AOP可以实现防止表单重复提交,本文主要介绍了SpringBoot整合redis+Aop防止重复提交的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • SpringBoot中实现Druid前端监控界面自动登录功能

    SpringBoot中实现Druid前端监控界面自动登录功能

    这篇文章主要介绍了SpringBoot中实现Druid前端监控界面自动登录功能,需要的朋友可以参考下
    2024-08-08
  • Java的反射机制之获取class详解

    Java的反射机制之获取class详解

    这篇文章主要介绍了Java的反射机制之获取class详解,Class类表示一个类或接口的元数据,通过它可以获取到类或接口的构造函数、方法、字段、注解等信息,也能够创建对象、调用方法等,需要的朋友可以参考下
    2023-09-09
  • Java中实现日志记录的方案总结

    Java中实现日志记录的方案总结

    在平时使用到一些软件中,比如某宝或者某书,通过记录用户的行为来构建和分析用户的行为数据,这就需要使用到日志系统来存储或者记录数据,小编为大家整理了几种Java日志方案,希望对大家有所帮助
    2024-12-12
  • 使用Springboot处理跨域的方式

    使用Springboot处理跨域的方式

    这篇文章主要介绍了使用Springboot处理跨域的方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-09-09
  • java中Scanner输入用法实例

    java中Scanner输入用法实例

    Java的Scanner用法,主要用于算法笔试时的控制台输入,下面这篇文章主要给大家介绍了关于java中Scanner输入用法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • 基于FLink实现实时安全检测的示例代码

    基于FLink实现实时安全检测的示例代码

    这篇文章主要为大家详细介绍了如何基于FLink实现实时安全检测的功能,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的可以了解一下
    2023-02-02
  • java数据结构排序算法之树形选择排序详解

    java数据结构排序算法之树形选择排序详解

    这篇文章主要介绍了java数据结构排序算法之树形选择排序,结合具体实例形式分析了java树形选择排序的原理、实现技巧与相关注意事项,需要的朋友可以参考下
    2017-05-05
  • Resty开发restful版本的Jfinal深入研究

    Resty开发restful版本的Jfinal深入研究

    这篇文章主要为大家介绍了Resty开发restful版本的Jfinal深入研究有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03

最新评论