剑指offer-[编程题]不用加减乘除做加法(python2实现及解析)

题目来源:牛客网
题目描述:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
参考答案:

class Solution: 
    def Add(self, a, b):           
        while(b): 
           a,b = (a^b) & 0xFFFFFFFF,((a&b)<<1) & 0xFFFFFFFF
        return a if a<=0x7FFFFFFF else ~(a^0xFFFFFFFF)

原答案提供者的解析:

不得不吐槽下Python对位操作简直是深坑一座- -主要原因还是因为python没有无符号又移操作(根据原题,此处应为左移,估计是笔误),所以需要越界检查一波~其他思路和大家是一样的加法是异或,进位是与<<1

原解析来源:
https://www.nowcoder.com/questionTerminal/59ac416b4b944300b617d4f7f111b215

---------------------------------分割线 ------------------------------------
由于本人计算机基础还不算牢靠,所以理解这个答案花费了一定时间,把我的理解记录在这里,供参考。如果有不妥的地方欢迎大家指正。
首先,这个问题的解决思路已经比较清晰(以下为剑指offer中原书的解析):
在这里插入图片描述
在这里插入图片描述

这个解析的说明很清晰,问题的关键是python中的位运算的实现细节。
根据我个人的理解,解决方案中有以下关键点:

1.原码、反码与补码

此处可以参考下面链接的博文:
https://blog.csdn.net/lrs1353281004/article/details/87188518

2.越界检查

就是答案中的 & 0xFFFFFFFF 操作,其中 & 是按位与, 0xFFFFFFFF代表16进制下的边界 (按二进制表示的话,对应4*8=32位)。
由于python长整数类型可以表示无限位,所以需要人为设置边界,避免死循环。
设置成32位应该是考虑到其他语言的特点,测试样例中不会出现超过32位整型的数,实际上,把边界调大的话,不会影响最终结果。

关于python可以表示无限位整数,可以参考下面链接:
https://segmentfault.com/a/1190000015284473

3.正负数判断及还原

正数与边界数 按位与(&) 操作后 仍得到这个数本身:
在这里插入图片描述
负数与边界数 按位与(&) 操作后 得到的是对应二进制数的真值:
在这里插入图片描述
为了便于理解,以一个小边界为例:
在这里插入图片描述
241 对应的二进制数为: 11110001

答案中,通过查看符号位(最高位,即与0x7FFFFFF比较大小)判断a为正数还是负数,正数则直接返回。负数则返回~(a^0xFFFFFFFF)。 (注: ~ 表示按位取反)

此处操作最终返回的是原来负数的值:
在这里插入图片描述
11110001^0xFFFFFFFF -----> 00001110
~(00001110) -----> 11110001(补码) ,对应的十进制数是 -15
此处有一个规律:
~n = -(n+1)
参考下面链接:
https://blog.csdn.net/Strive_Chuan/article/details/79242010

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值