美文网首页
[python2] 65 不用加减乘除做加法、减法

[python2] 65 不用加减乘除做加法、减法

作者: cca1yy | 来源:发表于2019-08-27 18:40 被阅读0次

1. 不用加减乘除做加法

题目描述
#方法一:使用位运算
# -*- coding:utf-8 -*-
# -*- coding:utf-8 -*-
class Solution:
    def Add(self, num1, num2):
        # write code here
        while num2:
            mainPart = num1^num2 #不带进位的加法,1 + 1 = 0; 1 + 0 = 1; 0 + 1 = 1; 0 + 0 = 0;相当于异或运算
            num2 = ((num1&num2)<<1) #只得到加法计算的进位,1 + 1 = 0; 0 + 1 = 0; 1 + 0 = 0; 0 + 0 = 0;相当于与运算
            # 其实1 + 1之后应该变成10和nonCarry相加从而得到最终的和。因此相当于与运算之后左移一位
            num1 = mainPart&0xffffffff #截断,使得num1永远只有32位
            #截断的原因是python中int没有限制为32位
        #return num1 if num1<0x7fffffff else ~(num1^0xffffffff)
        return num1 if num1<0x7fffffff else -(((~num1)+1)&0xffffffff)
    #if num1<0x7fffffff,则num1为正数,否则,num1为负数
    #若num1为负数,则将其取反加1得到其相反数也就是正数形式,给正数加一个负号就得到了num1的正确值
#方法二:使用python自带的库
# -*- coding:utf-8 -*-
class Solution:
    def Add(self, num1, num2):
        # write code here
        return sum([num1, num2]) #注意这里必须传入一个list

2. 不用加减乘除做减法

1). 思路1

a - b = a + (-b) 因此可以使用上面的加法来间接达到减法的目的

!!!如何得到整数的相反数?取反加1

2). 思路二

位操作实现减法(以14 - 7 为例)

首先将被减数 14 和 减数 7 都转化为二进制,看看二进制减法如何运算。

(14) 10 = (1110) 2
(7) 10 = (0111) 2

二进制减法运算,遇到 0 - 1 时,需要从前面的1借2,虽然结果仍然等于1,但是前面的那一位变成0。其它三种情况如0 - 0 = 0; 1 - 0 = 1; 1 - 1 = 0,都可以直接运算,不存在借位的问题。因此,在实现减法的过程中,应该着重考虑借位的情况。

若不考虑借位的情况,则0 - 0 = 0; 1 - 0 = 1; 0 - 1 = 1;1 - 1 = 0;这个操作等同于异或运算。

对于借位的情况,我们假设不从前一位数借位,而是从上天借位,计算得到差之后,再还给上天即减去借来的位即可。只有在被减数为0,减数为1时才需要借位,而且借来的数值为10,即减数为左移一位。为了能够顺利找出这种情况,我们先将被减数为1,减数为1的可能性排除,在不考虑借位的情况下,被减数的1永远都不会由于借给别人而变成0,因此若被减数为1,减数也为1,二者的差一定为0,于是我们想办法去除被减数为1,减数也为1的这些位,剩下的位,若减数为1,被减数一定为0,则需要向上天借位。

如何去除被减数a和减数b中,被减数为1,减数也为1的这些位呢?首先 a & b则只剩下被减数为1,减数也为1的位是1,其他位都为0。然后再使用a = a & b ^ a和 b = a & b ^ b,此时的 a 和 b就去掉了同时为1的位,变成同时为0.

\color{blue}{综上所述,在使用位运算进行减法 a - b 的运算时,} 1). 先 a&b得到a 和 b中都是1的位,然后使用a = a & b^ a和 b = a & b ^ b 得到新的a和新的b,它们不存在同时都是1的位。2). 使用nonBorrow = a ^ b 得到的nonBorrow,是不考虑借位时a - b的差值。3). 此时的 a 和 b,若减数b为1,被减数a一定为0,因此肯定会向上天借位,将减数b左移一位便是需要向上天借来的,使得 0 - 1 = 1的值。nonBorrow 是被减数a使用上天借来的位减去减数b的差值,使用nonBorrow - (b << 1)将借来的位还给上天,即为 a - b之后实际的差值。nonBorrow - (b << 1)仍然重复前两步的操作,将nonBorrow 作为被减数,b << 1作为减数,重复,直到b << 1 == 0为止。

# subtraction.py

class solution:
    def subtraction(self, num1, num2):
        allOneNum1 = self.getAllOne(num1) #获取与num2位数相同,但是值全是1的数
        # print("allOneNum1 = ", allOneNum1)
        while num2:
            # print("num2 = ", num2)
            temp = num1 & num2 # 取出num1和num2中同时为1的位
            num1 = temp ^ num1
            num2 = temp ^ num2 # 将num1和num2中同时为1的位,都置为0
            nonBorrow = num1 ^ num2 #不考虑借位的情况,1 - 1 = 0; 1 - 0 = 1; 0 - 1 = 1; 0 - 0 = 0,类似于异或操作
            num2 = (num2 << 1) & allOneNum1 #num2 << 1即向上天额外借来的数值,需要从nonBorrow中减去
            # 这里对num2 << 1之后的数需要截断,截断的标准为num1或num2中较长的位数,这里为了简便,使用被减数num1的位数
            num1 = nonBorrow & 0xffffffff #此时num1 = nonBorrow作为被减数,num2作为减数,继续相减直到num2 == 0
            # & 0xffffffff是为了在位数溢出时进行截断
        return num1 if num1 < 0x7fffffff else -((~num1 + 1) & 0xffffffff)
    
    # 获取与num2位数相同,但是值全是1的数(即获取位数相同时的最大值)
    def getAllOne(self, num_input):
        num_output = 1
        while num_input - 1:
            num_input = num_input >> 1
            num_output = (num_output << 1) + 1
        return num_output

if __name__ == "__main__":
    s = solution()
    sumResult = s.subtraction(1400, 7)
    print("140 - 7 = ", sumResult)
代码运行结果

其中,有一个比较重要的函数getAllOne(),主要是在num2左移时,需要限制num2左移的位数。python对于int并没有位数限制,因此,需要根据num1和num2的位数,对num2 << 1进行截断,才能使得左移之后的结果等于0. 这里根据一定的位数得到相同位数,值为1的数的方法为:由于我们输入的十进制数,最高位肯定是1,(若不是1,前面的0可以省略),因此,想要得到十进制数对应二进制数的位数,就将该二进制数右移,知道该二进制数等于1,此时就可以得知二进制数的位数。想要得到相同位数,但值为1的数,就在右移时用另外一个数1左移,并给左移后的数加1,就可以了。具体代码如上,这里打印了部分用例结果。

getAllOne()函数部分用例结果

参考:http://www.cppblog.com/qingbizhu/archive/2012/03/30/168148.html

相关文章

  • [python2] 65 不用加减乘除做加法、减法

    1. 不用加减乘除做加法 2. 不用加减乘除做减法 1). 思路1 a - b = a + (-b) 因此可以使用...

  • 65-不用加减乘除做加法

    写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”、“/” 四则运算符号。

  • 65.不用加减乘除做加法(简单)

    考点:本题考查发散思维能力 题目描述: 写一个函数,求两个整数之和,要求在函数体内不得使用 “+”、“-”、“*”...

  • 共勉

    加减乘除是曾国藩一生的写照,他用加法做事,用减法生活,用乘法感恩,用除法放下。 用加法做事。人生最难的莫过于做加法...

  • 剑指offer第二版-65.不用加减乘除做加法

    本系列导航:剑指offer(第二版)java实现导航帖 面试题65:不用加减乘除做加法 题目要求:写一个函数,求两...

  • BigDecimal

    1. 加减乘除 加法 add 减法 subtract 乘法 multiply 除法 divide 2. 比...

  • 不用加减乘除做加法

    题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 分析 题目要求不能使用四...

  • 不用加减乘除做加法

    剑指 Offer 的一道题:求两个整数之和,不得使用 加 减 乘 除 四种运算符。其实仔细想一想,语言中除了这几种...

  • 不用加减乘除做加法

    题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 思路 递归采用 按位与 ...

  • 不用加减乘除做加法

    题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 示例 输入4 1输出5 ...

网友评论

      本文标题:[python2] 65 不用加减乘除做加法、减法

      本文链接:https://www.haomeiwen.com/subject/khvlnqtx.html