不用加减乘除做加法中Python存在的bug

本文探讨了在Python中实现不使用基本运算符的两数相加问题。通过位运算解决,并分析了正负数异或可能导致的无限循环问题。在Swift中的实验进一步验证了这一现象。

今天在刷《剑指offer》的时候,在做面试题47的时候,碰到了一道题:

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

题目本身也不太难,使用位的异或运算和 位与操作即可。代码如下:

class Solution:
    def Add(self, num1, num2):
        while num2:
            sum = num1 ^ num2
            carry = (num1 & num2) << 1
            num1 = sum
            num2 = carry
        return num1

但是我在测试用例的时候,选择了一个4, 一个-2, 发现很久都没有打印出结果。于是我就尝试按步骤分析一个正数和一个负数的位运算,发现在这个过程中,sum = num1 ^ num2这句话中,在不断的迭代中变成了一个越来越小的负数, 这时候我大约猜出来了不出结果的原因了。
因为在python早期版本中如Python2.7中,整数的有int和long两个类型。int类型是一个固定位数的数;long则是一个理论上可以存储无限大数的数据类型。当数大到可能溢出时,为了避免溢出,python会把int转化为long。而Python3.x之后整数只有一个可以放任意大数的int了。可是无论哪种,都是采用了特殊的方法实现了不会溢出的大整数。
因此,在计算正数和负数异或的时候,Python就会不断的算啊算,算啊算。。。

之后我利用Swift模拟了一下,毕竟强大的Swift可以直接显示出中间计算的结果,测试用例还是4和-2。直接上图:

运行结果

异或结果截图如下所示:

sum

异或sum取的值如下所示,也能够更直观的看出来,在计算一个正数和负数进行按位加法的时候,必须要先溢出才能求得正确的答案:

-6
-14
-30
-62
-126
-254
-510
-1022
-2046
-4094
-8190
-16382
-32766
-65534
-131070
-262142
-524286
-1048574
-2097150
-4194302
-8388606
-16777214
-33554430
-67108862
-134217726
-268435454
-536870910
-1073741822
-2147483646
-4294967294
-8589934590
-17179869182
-34359738366
-68719476734
-137438953470
-274877906942
-549755813886
-1099511627774
-2199023255550
-4398046511102
-8796093022206
-17592186044414
-35184372088830
-70368744177662
-140737488355326
-281474976710654
-562949953421310
-1125899906842622
-2251799813685246
-4503599627370494
-9007199254740990
-18014398509481982
-36028797018963966
-72057594037927934
-144115188075855870
-288230376151711742
-576460752303423486
-1152921504606846974
-2305843009213693950
-4611686018427387902
-9223372036854775806
2

综上所述,可以知道:Python搞东西确实方便,但是效率很低,让容纳很大的数确实省去了考虑大数的烦恼,但是事出反常必有妖,这个不能溢出有时候也很闹人啊。。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值