题目

  给定两个32位整数a和b,可正、可负、可0.不能使用算术运算符,分别实现a和b的加减乘除。

要求

  如果给定的a和b执行加减乘除的某些结果本来就会导致数据的溢出,那么你实现的函数不必对那些结果负责。

基本思路

 加法运算

  使用位运算实现加法运算主要分为两个部分。先计算完全不考虑进位进行相加的结果,再计算只考虑进位的产生值。将两个结果相加就是最终的结果。

  例如: 
  a:    001010101 
  b:    000101111

首先不考虑进位进行相加,结果为001111010,该结果其实就是a ^ b。

再考虑进位的产生值,结果为000001010,该结果其实就是(a & b)<< 1。

将1、2产生的结果再相加,此时依然要考虑两部分:不考虑进位和只考虑进位。

一直重复上述步骤,直到进位产生的值全部消失。

private int add(int a,int b){int sum = a;while(b!=0){sum = a^bb = (a&b) << 1a = sum}return sum}

减法运算

实现a - b只要实现a + (-b)即可。所以只要将a和b的相反数调用add函数就行。根据二进制数在机器中表达的规则,得到一个数的相反数,就是这个数的二进制数表达取反加1(补码)的结果

public int negNum(int n){return add(~n,1)
}public int minus(int a,int b){return add(a,negNum(b))
}

乘法运算

用位运算实现乘法运算。a × b的结果可以写成 a∗20∗b0+a∗21∗b1+...a∗2i∗bi+...a∗231∗b31a∗20∗b0+a∗21∗b1+...a∗2i∗bi+...a∗231∗b31. 其中bibi为0或1表示整数b的二进制表达中第i位的值(从右往左数)。该过程有点类似于求整数的N次方问题。具体实现参照如下代码

public 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;
}

除法运算

  用位运算实现除法运算其实就是乘法的逆运算。定义 res 表示除法的结果。首先将a向右移位31位,然后看能不能容下b,如果能,说明a/231a/231可以包含一个b,等价于a可以包含一个b∗231b∗231,令res的第31位为1,此时a的值应该为a−b∗231a−b∗231;如果不能容下b,令res的第31位为0,a的值不变;接下来将a向右移位30位是否能容下b……重复步骤直到a−b∗2i=0a−b∗2i=0。 
  以上过程只适用于a和b都不是负数的情况下,当a或b为负数时,可以先将a和b转成正数,计算完之后再判断res的真实符号就行。 
  除法实现到这一步已经可以解决绝大多数情况了。但是我们知道,32位最小整数的绝对值要比最大整数大,所以如果a或b等于最小值,是不能转换成相对应的正数的。这时候需要分情况考虑:

如果a和b都为最小值,直接返回1

如果a不为最小值,而b为最小值,那么a/b = 0,直接返回0

如果a为最小值,而b不为最小值。这时我们对a无能为力,但是我们可以让a增大一点点,计算出一个结果然后再修正一下就可以得到最终的结果。处理过程如下:

  <1>计算(a+1)/b(a+1)/b,结果记为c 
  <2>计算c∗bc∗b 
  <3>计算(a−c∗b)/b(a−c∗b)/b,结果记为rest 
  <4>计算c+rest

public boolean isNeg(int n){return n<0;
}public int div(int a,int b){int x = isNeg(a) ? negNum(a):a;int y = isNeg(b) ? negNum(b):b;int res = 0;for (int i = 31;i>-1;i=minus(i,1)){if ((x>>i)>=y){res |= (1<<i);x = minus(x,y<<i);}}return isNeg(a)^isNeg(b) ? negNum(res):res;
}public int divide(int a,int b){if(b==0){throw new RuntimeException("divisor is 0");}if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE){return 1;}else if (b == Integer.MIN_VALUE){return 0;}else if (a == Integer.MIN_VALUE){int res = div(add(a,1),b);return add(res,div(minus(a,multi(res,b)),b));}else{return div(a,b);}
}

只用位运算不用算术运算实现相关推荐

  1. 只用位运算来实现整数的加减乘除四则运算

    首先回忆计算机组成原理学过的内容,数字在机器ALU运算逻辑单元内部是以补码形式进行运算的,因为补码有两个优势: 1.能做到符号位和数值部分一起运算,这样无需单独考虑符号. 2.能把减法运算转化为加法运 ...

  2. 位运算常用技巧分析汇总(算法进阶)

    文章目录 运算性质 异或运算的一些性质 秀秀伸手 1.只用位运算来完成两个整数相加 2.不用临时变量,交换a.b两个数的值 3.判断一个数是奇数还是偶数 3.快速计算2*n.2*n+1和n/2 4.` ...

  3. 用位运算完成大小比较

    目录 只用位运算完成大小比较 写在后面 只用位运算完成大小比较 如何不用任何比较判断语句,就可以返回两个数中较大的那个 /*** @author 杨思远* @version 1.0* @title 位 ...

  4. 位运算详解+竞赛常见用法总结

    目录 一.位运算详解 二.位运算应用 1.快速幂 2.给定一个数组A, 长度为n,求下面这段程序的值 3.数数字 4.数数字 2 5.nim博弈问题: 6.树状数组 7.判断一个数x是不是2的某次方 ...

  5. 位运算简介及实用技巧(二):进阶篇(1)

    =====   真正强的东西来了!   ===== 二进制中的1有奇数个还是偶数个     我 们可以用下面的代码来计算一个32位整数的二进制中1的个数的奇偶性,当输入数据的二进制表示里有偶数个数字1 ...

  6. 位运算(转自matrix67)

    http://www.matrix67.com/blog/archives/263 (原文链接) 什么是位运算? 程序中的所有数在计算机内存中都是以二进制的形式储存的.位运算说穿了,就是直接对整数在内 ...

  7. 剑指 Offer 65. 不用加减乘除做加法(位运算、递归、迭代)

    一.题目 剑指 Offer 65. 不用加减乘除做加法 题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用 "+"."-"."*" ...

  8. 超简单的位运算---再也不用担心看不懂题解了

    超简单的位运算---再也不用担心看不懂题解了 写在前面 1.原码.反码与补码------整形在计算机中的储存 2.移位操作符 3.位操作符 4.小练手 写在最后 写在前面 大家好,这里是风扇的小小笔记 ...

  9. [GO语言基础] 四.算术运算、逻辑运算、赋值运算、位运算及编程练习

    作为网络安全初学者,会遇到采用Go语言开发的恶意样本.因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识:另一方面是分享与读者,希望大家一起进步.前文介绍了Golang的 ...

最新文章

  1. 这道「传说级」的数学题,为什么有 3 个正确答案?
  2. 读书笔记-我所理解的生活
  3. SAP云平台 Document Information Extraction服务测试
  4. android 5.0 设置铃声,android5.0联系人铃声设置和来电读取分析
  5. c语言素数程序出现大空行,C语言实现寻找大素数
  6. html-iframe_HTML iframe
  7. 客户端跳转与服务器跳转的区别
  8. Objective-C和C++混编的要点
  9. 腾讯二面:引入RabbitMQ后,你如何保证全链路数据100%不丢失 ?
  10. latex导数_使用LaTeX语法编写数学公式(持续更新)
  11. 五笔字根表识别码图_五笔输入法口诀(五笔字根表快速记忆图)
  12. 群晖让usb打印机变成网络打印机
  13. Spark学习:Win10中编译Spark源码
  14. html 静止横屏_移动端开发-禁止横屏
  15. Endnote实用快捷键
  16. ELK之Kibana入门及使用
  17. 虾皮 店铺如何获取免费流量?5种引流量办法
  18. EMC磁珠到底什么样的特性
  19. java是高级还是低级语言_程序员:高级与低级编程语言,您应该学习哪些内容?...
  20. MTTF,MTBF,MTRF的概念

热门文章

  1. Centos7 Docker Jenkins ASP.NET Core 2.0 自动化发布和部署
  2. jQuery和AngularJS的区别小分析
  3. HBase 6、用Phoenix Java api操作HBase
  4. Lync Server 2013与OWA的集成
  5. JAVA 对象引用,以及对象赋值
  6. XP系统限制修改IP有新招
  7. 构造函数的初始化,初始化列表还是大括号里好,那种效率高
  8. Linux MySQL Connector/C++ 编程实例
  9. 浅谈安卓线程池相关问题
  10. laravel php配置,PHP Laravel框架路由配置及设置技巧全解