ビットごとの演算子(|、&、〜、^、>>、<<)と、+、-、!などの他の基本的な演算子のみを使用して、以下の「==」を置き換えることはできますか?
int equal(int x, int y) {
return x == y;
}
2つの数値に違いがない場合、それらは等しくなります。
int equal(int x, int y){
return !(x-y);
}
XOR
はNOT EQUALS
とまったく同じであり、XNOR
はEQUALS
とまったく同じであることに注意してください。したがって、次のようにすると、正確に必要なものが得られます。
return !(x ^ y);
C !
演算子は実際には!= 0
の省略形なので、これを使用することは不正行為に非常に近いようです:)
これは、ビット単位の演算を使用した私の考えです。32ビットの2の補数マシンで算術右シフトを想定しています(厳密には、Cの算術右シフトは未定義ですが、2の補数マシンでこれまでに見たすべてのCコンパイラはこれを正しくサポートしています)。
int t = (x - y) | (y - x); // <0 iff x != y, 0 otherwise
t >>= 31; // -1 iff x != y, 0 otherwise
return 1 + t; // 0 iff x != y, 1 otherwise
とはいえ、実際のコンパイラにはこの問題はありません。実際のハードウェアは、比較を直接サポートしています。詳細はアーキテクチャによって異なりますが、2つの基本モデルがあります。
より多くのRISCのようなプラットフォームには、通常、比較を行い、結果に基づいて分岐する直接の「等しい場合の分岐」および「より小さい場合の分岐」オペランドがあります。基本的にはCコードと同等です
if (a == b) goto label;
または
if (a < b) goto label;
すべて1つの機械語命令で。
この例は減算と同じですが、一部のアーキテクチャがレジスタ比較をどのように行うかについてより明確です(ARMなど)。
return !(1 + ~x + y);
1は、ALUへのキャリービット入力を示します。 1つの数値x
はビット単位で補われます。補数を取り、1を加えると、数値の2の補数が生成されます(x
は-x
)、それから他の数値に加算して、等しいかどうかを判断するための差を取得します。
したがって、両方の数値が等しい場合、-x + x => 0
。
(レジスタレベルでは!
演算子は実行されず、条件コードまたはフラグレジスタの「ゼロビット」をテストするだけです。これは、レジスター操作がゼロの結果を生成する場合に設定され、それ以外の場合はクリアされます。)
XORは(!=)と同じであるため、(x ^ y)は等しい値に対してのみ0を返します。賢明であり、ビットごとの演算子を使用し、 。
int notEqual(int x, int y){
return (x ^ y);
}
これについての私の見解
int equal(int x, int y){
if((x & ~y) == 0)
return 1;
else
return 0;
}
説明:x == y
の場合、x & ~y
は0
に評価されて1を返し、それ以外の場合はx!=y
として0を返します。
Edit1: The above is equivalent to
int equal(int x, int y){
return !(x & ~y) ; // returns 1 if equal , 0 otherwise.
}
上記のコードは、最上位ビットが1になる特定の場合に失敗します。解決策は1を追加することです。つまり、正しい答えは
return !(x & (~y +1) );