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

目录
  • 前言
  • 思路分析
    • 示例
    • 位运算进位
    • 初步结果
    • 去除加号
  • 整体思路
  • 加法代码实现
  • 减法实现
    • 减法分析
    • 减法代码实现
  • 总结

前言

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

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

思路分析

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

示例

假设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位运算实现加减运算内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java利用位运算实现加减乘除的方法详解

    目录 前言 一.常见位运算 1. &运算 2. |运算 3. ^运算 4. ~运算 二.位运算实现加法 三.位运算实现减法 四.位运算实现乘法 五.位运算实现除法 前言 我们经常使用的加减乘除,我们所看到的只是表面的效果,那么加减乘除在底层究竟是怎么实现的?今天就让我们一探究竟.今天用位运算实现的加减乘除不使用任何的加减乘除符号. 一.常见位运算 1. &运算 &运算二进制每一位全1为1,否则为0 public static void main(String[] args) { i

  • 一定要让你搞懂Java位运算符

    目录 常用的运算符 位运算符 &.|.^ 运算符 ~ 运算符 << 和 >> 运算符 >>> 运算符 有<<<运算符吗 总结 常用的运算符 在Java语言中,官方给我们提供了极为丰富的运算操作,但是常用的,好像也就是算术运算符,例如加.减.乘.除.取余等.还有就是关系运算符大于.小于.等于.不等于等.再或者就是逻辑运算符&&.||.!等,至于位运算符,属实用的不多.用的不多今天为什么拿出来讲呢,首先这可以帮助你很好的去理解

  • Java利用位运算实现比较两个数的大小

    目录 题目要求 主要思路 方法1(不考虑溢出) 方法2(考虑溢出情况) 题目要求 如何不要用任何比较判断符(>,==,<),返回两个数( 32 位整数)中较大的数. 主要思路 方法1(不考虑溢出) 要比较 a 和 b 的大小,因为不能用比较符号,我们可以通过 a - b 的符号位来判断,如果 a - b 的符号位是 1,说明 a - b < 0,则 a 小,否则 a 大或者 a 和 b 相等. 如何判断一个数的符号位是 0 还是 1 ? 由于是 32 位整数,所以如果将一个数右移 31

  • Java中的位运算符全解

    目录 1.&(按位与运算符) 2.|(按位或运算符) 3.^(异或运算符) 4.<<(左移运算符) 5.>>(右移移运算符) 6.~(取反运算符) 7.>>>(无符号右移运算符) (1)正数无符号右移 (2)负数无符号右移 总结 1. &(按位与运算符) &按位与的运算规则是将两边的数转换为二进制位,然后运算最终值,运算规则即(两个为真才为真):1&1=1 , 1&0=0 , 0&1=0 , 0&0=0 pu

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

    目录 前言 思路分析 示例 位运算进位 初步结果 去除加号 整体思路 加法代码实现 减法实现 减法分析 减法代码实现 总结 前言 本文主要介绍如何使用位运算来实现加减功能,也就是在整个运算过程中不能出现加减符号. 加减乘除运算在计算机中,实际上都是用位运算实现的,今天就用位运算来模拟下加法和减法的运算功能. 思路分析 先分析如何用位运算实现加法运算. 示例 假设a=23,b=36,使用位运算实现加法得到结果59. 首先来看下23.36.59的二进制信息. 从上面的图中可以看到,两个数相加的结果与

  • Java 利用dom方式读取、创建xml详解及实例代码

    Java 利用dom方式读取.创建xml详解 1.创建一个接口 XmlInterface.Java public interface XmlInterface { /** * 建立XML文档 * @param fileName 文件全路径名称 */ public void createXml(String fileName); /** * 解析XML文档 * @param fileName 文件全路径名称 */ public void parserXml(String fileName); }

  • Java利用StampedLock实现读写锁的方法详解

    目录 概述 StampedLock介绍 演示例子 性能对比 总结 概述 想到读写锁,大家第一时间想到的可能是ReentrantReadWriteLock.实际上,在jdk8以后,java提供了一个性能更优越的读写锁并发类StampedLock,该类的设计初衷是作为一个内部工具类,用于辅助开发其它线程安全组件,用得好,该类可以提升系统性能,用不好,容易产生死锁和其它莫名其妙的问题.本文主要和大家一起学习下StampedLock的功能和使用. StampedLock介绍 StampedLock的状态

  • java中重写父类方法加不加@Override详解

    java重写父类方法加不加@Override 这个是我在刚学习java时遇到的问题,希望能给像我一样的新手学习时带来帮助,如有错误请指正,谢谢! class Father{ public String name; public int age; public Father(){ } public void work(){ System.out.println("盖房子"); } } class Son extends Father{ public int weight; public

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

    目录 前言 正文 十进制相乘 二进制相乘 思路分析 代码实现 总结 前言 在上一篇中,我们介绍了使用位运算实现加法和减法运算,接下来本文主要介绍如何用位运算实现乘法运算,在实现乘法时要用位运算实现,并且不能出现加减乘除任何符号. 之前介绍过一篇如何用位运算实现加法和减法: 如何用位运算实现加减运算? 正文 在用位运算实现之前,我们先来回忆一下小学时,学乘法时用的十字相乘法. 十进制相乘 例如,26 * 15,在进行乘法操作时,我们一般这样算,先用5乘以6得到30,把0写下把3记在一边,再用5乘以

  • C语言实现大整数加减运算详解

    前言 我们知道,在数学中,数值的大小是没有上限的,但是在计算机中,由于字长的限制,计算机所能表示的范围是有限的,当我们对比较小的数进行运算时,如:1234+5678,这样的数值并没有超出计算机的表示范围,所以可以运算.但是当我们在实际的应用中进行大量的数据处理时,会发现参与运算的数往往超过计算机的基本数据类型的表示范围,比如说,在天文学上,如果一个星球距离我们为100万光年,那么我们将其化简为公里,或者是米的时候,我们会发现这是一个很大的数.这样计算机将无法对其进行直接计算. 可能我们认为实际应

  • 使用MYSQL TIMESTAMP字段进行时间加减运算问题

    目录 MYSQL TIMESTAMP字段进行时间加减运算 计算公式如下 DATETIME 与 TIMESTAMP的区别 结论 参考文档 MYSQL TIMESTAMP字段进行时间加减运算 在数据分析过程中,想当然地对TIMESTAMP字段进行运算,导致结果谬之千里 计算公式如下 -- create_time与week_time的声明都是TIMESTAMP(), 要求精确到分钟 -- SELECT (sa.create_time - sa.week_time)/(1000 * 60) from a

  • ThinkPHP自定义函数解决模板标签加减运算的方法

    本文实例讲述了ThinkPHP自定义函数解决模板标签加减运算的方法.分享给大家供大家参考.具体如下: 实际项目中,我们经常需要标签变量加减运算的操作.但是,在ThinkPHP中,并不支持模板变量直接运算的操作. 幸运的是,它提供了自定义函数的方法,我们可以利用自定义函数解决: ThinkPHP模板自定义函数语法如下: 格式:{:function(-)} (参考官方帮助文档:http://thinkphp.cn/Manual/196) 利用这个,我们来试做加法和减法. 一.在ThinkPHP中定义

随机推荐