アルゴリズム-2つの数値の加算と減算、2つの実装方法を実現するために加算と減算の記号を使用しないでください

Leetcode-371

不使用运算符 + 和 - ​​​​​​​,计算两整数 ​​​​​​​a 、b ​​​​​​​之和。

示例 1:

输入: a = 1, b = 2
输出: 3
示例 2:

输入: a = -2, b = 3
输出: 1

1.加算記号と減算記号を使用せずに加算を実現します(I)

大物によって与えられたコードは確かに非常に簡潔ですが、同じことを理解することも困難です。これは非常に直感的な解決策です。
主なアイデア:
1。1<< 0から1 << 31までのマスクを作成します。対応するビット
2を検出するために、それぞれaとbでビット単位のANDを繰り返し実行します。対応するビットがすべて1の場合、1つのビットを伝送します。result| = mask << 1;
3.対応するビットの1つだけが1の場合、結果は次のようになります。現在のビットが0の場合、現在の位置は1です
。4。対応するビットが1として1つだけで、結果が1の場合、現在の位置は0、1ビットは
5であり、結果が返されます。

    public int getSum1(int a, int b) {
    
    
        int result=0;
        for(int i=0;i<32;i++){
    
    
            int mask=1<<i;
            if((a&mask)!=0&&(b&mask)!=0){
    
    //两个都是1,必然进位
                result|=mask<<1;
            }else if(!(((a&mask)==0)&&((b&mask)==0))){
    
    
                if((result&mask)==0){
    
    
                    result|=mask;
                }else{
    
    
                    result&=~mask;//清除原来位
                    result|=mask<<1;//进一位
                }
            }
        }
        return result;
    }

マスクを取得するときに++演算子が使用されますが、上記の記述は実際には問題ありません。
++演算子に対応するアセンブリ命令は、X86にマップされた後は実際にはINCですが、+はADDです。しかし、++はまだ少し不快に見えます。

この厄介な状況を回避するために、実際に考え方を変えることができます。つまり、マスクは実際に自分で取得できます。つまり、ループの各ラウンドの後、mask = mask << 1; mask == 1 << 31までループは終了します。このようにして、純粋なビット単位の操作によって得られる加算を取得します。


    public int getSum(int a, int b) {
    
    
        int result=0;
        int mask=0;
        while(true){
    
    
            mask=mask==0?1:mask<<1;
            if((a&mask)!=0&&(b&mask)!=0){
    
    //两个都是1,必然进位
                result|=mask<<1;
            }else if(!(((a&mask)==0)&&((b&mask)==0))){
    
    //其中某一个为1
                if((result&mask)==0){
    
    //如果现在位是0,那么将现在位变成1
                    result|=mask;
                }else{
    
    //如果现在位是1,那么要将当前位置0,高位放置1
                    result&=~mask;//清除原来位
                    result|=mask<<1;//进一位
                }
            }
            if(mask==1<<31){
    
    
                break;
            }
        }
        return result;
    }

2.加算記号と減算記号を使用せずに加算を実現します(II)

大物によって与えられた簡潔なコードは次のとおりです:

    public int getSum(int a, int b) {
    
    
    	while (b != 0) {
    
    
            int temp=a^b;//无进位累加值
            int carry=(a&b)<<1;//进位值
            //a=无进位累加值 b=进位值
            a=temp;
            b=carry;
        }
        return a;
    }

簡単に説明します
。1。キャリーなしの加算はXORによって実現され
ます。2。キャリー値はaとbの最上位ビットによって決定されます。2つの最上位ビットが両方とも1の場合、キャリー1ビットであり、aとbの最上位ビットはa&bによって決定されます。理解しやすく、最上位ビットのビット単位のANDの結果が最上位ビット1である場合は、1ビット左に移動します。これはキャリーです。キャリーが0になるまで、計算は終了します。

3.加算記号と減算記号を使用せずに減算を実現します

減算を達成する方法は?これは、正と負の数の変換を考慮に入れる必要があります。負の数= + 1で反転された正の数

    public int getSub(int a, int b) {
    
    
    	b=~b;//获得-b
    	b++;
    	while (b != 0) {
    
    
            int temp=a^b;//无进位累加值
            int carry=(a&b)<<1;//进位值
            //a=无进位累加值 b=进位值
            a=temp;
            b=carry;
        }
        return a;
    }

おすすめ

転載: blog.csdn.net/qq_23594799/article/details/105324292