web-dev-qa-db-ja.com

a ^ bおよび(a&b)<< 1とは何ですか?

私はこれをやっていた 質問 リートコードで。

リクエスト:

2つの整数aとbの合計を計算しますが、演算子+と-を使用することはできません。

それが与えた解決策を理解できません

誰かがこのgetSum関数の仕組みを説明できますか?

これがJSの答えです:

var getSum=function(a,b) {
    const Sum = a^b; //I can't understand how those two line's code can
    const carry = (a & b) << 1; //get the sum
        if(!carry) {
            return Sum
        }
    return getSum(Sum,carry);
};
console.log(getSum(5,1));
26
Jacky

_^_はビット単位の演算であるXORです。シングルビットでは、ルールは_0 ^ 0 = 0_、_0 ^ 1 = 1_、_1 ^ 0 = 0_、および_1 ^ 1 = 0_であり、マルチビット値を処理する場合は、対応するビットで実行するように拡張するだけです。この名前は「exclusive or」の略であり、AまたはBのいずれかが_A ^ B_である場合に限り、_1_が_1_であるという事実に由来します。両方ではありません。ただし、別の名前である⊕について話す方が興味深いです。 ⊕は+ですが、少し異なります。 ⊕の規則は、追加の規則に似ています:_0 + 0 = 0_、_0 + 1 = 1_、_1 + 0 = 1_、および_1 + 1 = 10_。 ⊕は+ですが、_1 ⊕ 1 = 0_は除きます。つまり、キャリーなしの場合を除いて、⊕は+です。これは複数のビットに当てはまります:_011 + 001 = 100_は、1の場所から_1_を2の場所に運び、次に_1_を再び4の場所に運びます。次に、_011 ⊕ 001 = 010_を実行します。

さて、本当の足し算をする時、いつ運ぶの?バイナリでは、答えは非常に簡単です。ある場所に_1_が2つある場合、_1_を次の場所に持ち込みます。これは、ビット単位のAND、_&_として簡単に理解できます。 _1 & 1 = 1_、それ以外の場合は_0_。 _011 + 001_の場合、キャリーなしで加算すると_011 ⊕ 001 = 010_が得られ、_1_のため、_011 & 001 = 001_を1の場所からキャリーする必要があることがわかります。 _(a & b) << 1_のシフトにより、数値は「どこから実行する必要がありますか」になります。 「キャリーを追加する場所はどこですか?」:_(011 & 001) << 1 = 010_; 2の場所にキャリービットを追加する必要があります。

したがって、getSumでは、_a + b_を知りたいと考えています。 _a ^ b_でキャリーなしで加算を計算し、_(a & b) << 1_でキャリービットを追加する必要がある場所を見つけます。次に、これら2つを加算するだけです。ええと、数値を一緒に加算する関数は既にあります。 getSumと呼ばれます。したがって、基本的にはfunction getSum(a, b) { return getSum(a ^ b, (a & b) << 1); }のみを記述します。ただし、実行するものがない場合は必ず短絡させ、無限再帰を回避します。

0
HTNW