两整数之和(剑指 Offer 65. 不用加减乘除做加法)

题目:

思路:

【1】这两道题本质上考察的是差不多的意思。

【2】这道题的本质上是考察二进制,因为在编程中数据是采用二进制进行存储的,所以便是要考察二进制的处理,即异或(^),相与(&)

理解异或 和 相与
异或: 当 1与1进行异或的时候得0,0与1异或的时候得1
相与: 当 1与1进行相与的时候得1,0与1相与的时候得0,0与0相与的时候得0

先分析 3+5 【这里采用的是tinyint来解释【可容纳-128~127,或无符号的0~255】,只有1字节(Bety),即8位(bit】:
3用二进制表示为00000011
5用二进制表示为00000101

那怎么表示3+5呢
先3^5【这里是全体异或哦,新手别懵】:
00000011^00000101=00000110=6
得出6明显还不是最终结果【因为只是将一部分像加到了一起】
此时还要处理进位问题
则3&500000011&00000101=00000001=1
因为这部分是两者都有的,所以相加到一起的话是需要进位的,那怎么进位呢?
x=3&5
x<<1【即采用位移,向左移动一位】
x<<1 = 00000010 = 2

此时重复步骤【即现在变为了6+2】
最终得到【8+0】即为结束

接下来分析3-5,可以看作为【3+(-5)】,
这需要了解一下概念
在Java/C++中正数和负数的存储方式
正数是以正码的形式存储
负数是以补码的形式存储

说明:
正码就是一个数的真实值,如00000011代表了1*(2^1)+1*(2^0)
而反码:就是正码取反,即11111100
而补码:就是反码加1,即11111101

那么3-5:
开始第一次
先x1=3^-500000011^11111011=11111000
则y1=3&-500000011&11111011=00000011
接着y1 = y1<<1 = 00000110

重复第二次:
先x2 = x1^y1
11111000^00000110=11111110
在y2 = x1&y1
11111000&00000110=00000000
最后y2 = y2<<1 = 00000000

代码展示:

采用异或运算的方案:

限制可以用变量个数的话,可以改为这样:

c=a&b;
a=a^b;
b=c<<1;
不限制的话下面这种会比较好看一点
class Solution {
    public int getSum(int a, int b) {
        int x,y;
        while (b!=0){
            x=a;
            y=b;
            a = x^y;
            b = (x&y)<<1;
        }
        return a;
    }
}

 

posted @ 2023-01-09 21:57  忧愁的chafry  阅读(116)  评论(0编辑  收藏  举报