Java利用位运算实现加减运算详解

 更新时间:2022年12月31日 09:34:46   作者:JavaCub  
这篇文章主要为大家介绍了如何使用位运算来实现加减功能,也就是在整个运算过程中不能出现加减符号。文中的示例代码讲解详细,感兴趣的可以了解一下

前言

本文主要介绍如何使用位运算来实现加减功能,也就是在整个运算过程中不能出现加减符号。

加减乘除运算在计算机中,实际上都是用位运算实现的,今天就用位运算来模拟下加法和减法的运算功能。

思路分析

先分析如何用位运算实现加法运算。

示例

假设a=23b=36,使用位运算实现加法得到结果59

首先来看下233659的二进制信息。

从上面的图中可以看到,两个数相加的结果与两个数异或的结果很相似,只不过在图中的2位置相加的时候,产生了进位,而异或是没有进位的,如果能拿到进位信息,把两个数异或的结果和进位信息的结果相加就能得到最终结果了,那么如果能拿到进位信息呢?

位运算进位

上图中,59的二进制信息可以分为两部分,01100110001000,再结合2336的二进制信息来看,01100112336的异或结果,而2336相与的结果跟0001000很相似,只不过0001000中的1比相与结果往前移了一位。

于是,我们可以得出,两个数的二进制进位信息为两个数的相与在左移一位。

初步结果

经过上面的分析,我们可以得到了一个初步的运算结果,即两个数相加等于两个数异或加上两个数的相与左移1位,也就是a + b = (a ^ b) + ((a & b) << 1)

先用2336来验证下。

经过验证可以看到,刚才得出的结论是正确的。

但是,我们要做到在整个运算过程中不能出现加号,接下来要想办法把这个加号给去掉。

去除加号

还是以2336为例,经过上面的运算我们把运算的位运算结果给化简下。

23 + 36 = (23 ^ 36) + ((23 & 36) << 1) = 51 + 8

也就是把2336的相加运算转化为了518的相加运算,接下来继续分析518的相加运算,也是通过异或和相与进行操作。

51 + 8 = (51 ^ 8) + ((51 & 8) << 1) = 59 + 0

嗯?可以发现我们已经得出59了,而且还加了个0,加了个0不就相当于加了个寂寞嘛,可以直接省略啊。

由此,我们又可以得出一个结论,两个数的二进制进位信息为两个数的相与在左移一位,不停地循环这个过程,直到有一个数变为0,就能得到结果。

整体思路

现在来总结下整体的计算过程:

  • 把两个数相加,拆分成两步,两个数异或加上两个数相与左移1位。
  • 判断相与左移的结果是否为0。
  • 如果相与左移为0,两个数异或的结果即为相加的结果。
  • 如果相与左移结果不为0,把得到的新结果,重复执行第1~3步操作。

加法代码实现

经过上面的分析,来看下代码实现。

public class Code19_Add {
   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 void main(String[] args) {
        int sum = add(23, 36);
        System.out.println(sum);
    }
}

运行程序,输出结果为59。

减法实现

减法分析

还是以2336为例,如果要计算 36 - 23,该怎么办?

36 - 23 不就相当于36 + (-23),可以理解为加上一个负数,这就可以了吗?不不不,要求的是不能出现加减符号,-23里面是有减法这个符号的。

还记得前面我们分析的负数可以怎么表示吗?对了,负数是对一个数的取反再加1。嗯?又出现加号了,不过加法我们不是已经实现了吗?直接拿来用就好了。

减法代码实现

有了加法操作,减法就很简单了,来看下代码。

public class Code20_Sub {
    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 sub(int a, int b) {
        return add(a, add(~b, 1));
    }
    public static void main(String[] args) {
        int sum = sub(36, 23);
        System.out.println(sum);
    }
}

运行一下输出结果为13

嗯,Perfect!

总结

本文主要介绍如何使用位运算来实现加减功能,至此功能都已经实现了。

那么问题来了,我们实现的加减运算与Java本身的加减相比,谁的效率更高呢?当然是Java中的更高了,因为我们是用Java实现的,代码运行后,要经过层层的翻译才能到达底层,所以效率肯定是有损失的。

当然我们的目的是熟悉位运算的操作,这个才是最重要的。

到此这篇关于Java利用位运算实现加减运算详解的文章就介绍到这了,更多相关Java位运算实现加减运算内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java中Collection、List、Set、Map之间的关系总结

    Java中Collection、List、Set、Map之间的关系总结

    今天小编就为大家分享一篇关于Java中Collection、List、Set、Map之间的关系总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • Json字符串内容比较超实用教程

    Json字符串内容比较超实用教程

    这篇文章主要介绍了Json字符串内容比较-超实用版,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • SpringBoot的@Conditional条件注解详解

    SpringBoot的@Conditional条件注解详解

    这篇文章主要介绍了SpringBoot的@Conditional条件注解详解,打开每个自动配置类,都会看到@Conditional或其衍生的条件注解,本节我们来认识下@Conditional注解,需要的朋友可以参考下
    2023-12-12
  • SpringBoot整合UEditor的示例代码

    SpringBoot整合UEditor的示例代码

    本篇文章主要介绍了SpringBoot整合UEditor的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-02-02
  • 基于Jenkins自动打包并部署docker环境的操作过程

    基于Jenkins自动打包并部署docker环境的操作过程

    这篇文章主要介绍了基于Jenkins自动打包并部署docker环境,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • Java多线程和并发基础面试题(问答形式)

    Java多线程和并发基础面试题(问答形式)

    多线程和并发问题是Java技术面试中面试官比较喜欢问的问题之一。在这里,从面试的角度列出了大部分重要的问题,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Spring循环依赖的解决方案详解

    Spring循环依赖的解决方案详解

    这篇文章将用实例为大家详细介绍了介绍如何解决Spring的循环依赖问题,文中的示例代码讲解详细,对我们学习Spring有一定的帮助,需要的可以参考一下
    2022-07-07
  • OpenCV实现普通阈值

    OpenCV实现普通阈值

    这篇文章主要为大家详细介绍了OpenCV实现普通阈值,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • 完美解决单例设计模式中懒汉式线程安全的问题

    完美解决单例设计模式中懒汉式线程安全的问题

    下面小编就为大家带来一篇完美解决单例设计模式中懒汉式线程安全的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • Spring cloud config 配置文件加密方式

    Spring cloud config 配置文件加密方式

    这篇文章给大家介绍了Spring cloud config 配置文件加密方式,非常不错,具有一定的参考借鉴价值,感兴趣的朋友跟随脚步之家小编一起学习吧
    2018-05-05

最新评论