今天在刷《剑指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取的值如下所示,也能够更直观的看出来,在计算一个正数和负数进行按位加法的时候,必须要先溢出才能求得正确的答案:
-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搞东西确实方便,但是效率很低,让容纳很大的数确实省去了考虑大数的烦恼,但是事出反常必有妖,这个不能溢出有时候也很闹人啊。。。。