LintCode 1【A + B 问题】

1. A + B 问题

给出两个整数 aa 和 bb , 求他们的和。

样例

样例  1:
	输入:  a = 1, b = 2
	输出: 3
	
	样例解释: 
	返回a+b的结果.

样例 2:
	输入:  a = -1, b = 1
	输出: 0
	
	样例解释: 
	返回a+b的结果.

挑战

显然你可以直接 return a + b,但是你是否可以挑战一下不这样做?(不使用++等算数运算符)

说明

a和b都是 32位 整数么?


代码

class Solution:
    """
    @param a: An integer
    @param b: An integer
    @return: The sum of a and b 
    """
    def aplusb(self, a, b):
        # write your code here
        if (a == 0):
            return b
        if (b == 0):
            return a
        x1 = a ^ b
        x2 = (a & b) << 1
        return aplusb(x1, x2)

1.1 正数
十进制下:5 + 7 = 12

5: 0101

7: 0111

二进制下两数求和,分三步:

各位值相加,不算进位值,二进制亦或运算
计算进位值,二进制与运算,然后左移一位;
对1,2步的结果,重复以上两步骤
两数之和就是不计算进位值加上进位值,直到没有进位

第二部为什么要左移?

当你在十进制下计算5+7时,进位向前一位进1,也就是相当于左移

5 + 7的详细计算:

第一次:

亦或:0101^0111 = 0010,没有进位的值。

与:0101&0111 = 0101,等于1的位说明这一位是要产生进位的。而进位是要向前进一位,所以要左移,

0101 ,两个位置为1,说明是有两个位置需要进位,左移运算,0101<<1 = 1010

第二次:

0010^1010 = 1000

(0010&&1010)<<1 = 0100 # 还有进位,需要继续加

第三次:

1000^0100 = 1100

(1000&&0100) <<1= 0000 # 没有进位

进位为0,返回第一步的结果。

1.2 负数
博客上好多教程都是以正数为例来解释,让好多读者误认为二进制的运算是在源码上进行的。

实际情况是用补码运算的!!!

因为正数的源码、反码、补码是相等的,所以大家误认为是用的源码。

python3 中最高位1表示负数,最高位0表示正数

(个人认为,用补码运算是因为可以把符号位直接参与运算)

源码转化成补码:源码转化成反码(符号位1不变,其他位改变),然后反码+1

补码转化为源码:你只需要记住,补码的补码就是源码

所以补码转反码,然后+1

例如 -2 + 8

用8位二进制表示:

-2 源码 :1000 0010;反码:1111 1101;补码:1111 1110

8 源码/反码/补码:0000 1000

用补码运算结果如下:

1、1111 1110^0000 1000 = 1111 0110 (负数)转化成源码:1000 1010 = -10

2、(1111 1110&0000 1000)<<1 = 0001 0000 (正数),源码和补码一样:0001 0000 = 16

这是用补码运算的例子。

继续运算:

进位为16,继续计算1,2步,你会发现进入死循环。

因为:python3实现不会溢出,溢出的最高位不会舍弃掉。详细请看博文:https://www.jianshu.com/p/21fd1598d4ae

这种方法在c,c++,java中没有问题。但在python3中会有问题,python3存的正数是无限大的


引用

题目来源:https://www.lintcode.com/problem/ 

参考:https://blog.csdn.net/ustbbsy/article/details/82344003

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值