2012-04-14 7 views
2

私は24人以下の演算子を持つビット方式を作成する必要がある宿題をしています。私のコードは動作しますが、私は25人のオペレータを持っています。誰かがコードを実行するより効率的な方法を見つけることができますか?私の方法は、より少ない演算子を使用する必要があります

int isGreater(int x, int y) 
    { 
     int xSign = (x>>31); 
     int ySign = (y>>31); 
     int check1 = (xSign & ySign) | (~xSign & ~ySign); 
     int same = !(((x + ((~y) + 1))>>31) & 0x1); 
     int check2 = (check1 & same) | (~check1 & !xSign); 
     int equal = ((!(x^y))<<31)>>31; 
     return 0 | (~equal & check2); 
    } 

答えて

6

この行を変更してみてください。このため

int check1 = (xSign & ySign) | (~xSign & ~ySign); 

:1つの少ないオペレータの

int check1 = (xSign & ySign) | ~(xSign | ySign); 

+3

1 :) – ulmangt

+1

完璧ですありがとうございました! – Guambler

4

check1に過ぎない(任意の効果を持っていない0とビット単位or

return (~equal & check2);

return 0 | (~equal & check2);

に簡略化することでした。 a xnor。なぜあなたはこれを置き換えるものではありません。これで

int check1 = (xSign & ySign) | (~xSign & ~ySign); 

int check1 = ~(xSign^ySign); 

バージョンは、鉱山はあなたのコードがあなたであれば、より美的になります。2.

注5ビット単位の演算子を持っています

int check1 = !(xSign^ySign); 

ビット単位の否定ではなく論理否定ですが、正当性については心配しないでくださいとにかくすべての上位ビットを削除します。

2

あなたがこの置き換えることができ、int sが32ビット幅であると仮定すると:これで

int equal = ((!(x^y))<<31)>>31; 

int equal = ((!(x^y)) & 0x1; 

をそして、まだ別のものを自分で保存します。

1

あなたは明らかに加えを使用することができますので、それははるかに簡単な方法があります私には思える:

int isGreater(int x, int y) { 
    return ((unsigned)(~x + 1 + y)>>31) & 1; 
} 

基本的な考え方は非常に単純です - YからXを減算し、結果は陰性であったかどうかを確認してください。少なくとも少しの挑戦をするために、私は直接減算をすることはできないと仮定していますので、自分自身を否定する必要があります(2の補数を使用してビットを反転して追加します)。

5人の演算子 - キャストを含めると6つ。

注目に値する点:sameの計算は、それ自体ではかなり適切でした(実際には過剰なことですが、論理否定を排除する必要があります)。[:より多くの境界条件を含むように更新テストコードの編集]:簡単なテストを行う

int main() { 
    std::cout << isGreater(1, 2) << "\n"; 
    std::cout << isGreater(1, 1) << "\n"; 
    std::cout << isGreater(2, 1) << "\n"; 
    std::cout << isGreater(-10, -11) << "\n"; 
    std::cout << isGreater(-128, 11) << "\n"; 
    std::cout << isGreater(INT_MIN, INT_MIN) << "\n"; 
    std::cout << isGreater(INT_MAX, INT_MAX) << "\n"; 
    return 0; 
} 

0 
0 
1 
1 
0 
0 
0 
0 

は...すべての予想通り。

+0

問題は...私も負の数に対処する必要があります参照してください。だからあなたのコードは、私のintと同じように動作します...しかし、両方の数値が正の場合に限ります。私の特別なコードは、xとyが正か負かをチェックすることでした。私はまた、2つの数字がすべてのベースをカバーするためにお互いに等しいかどうかを確認しました。 – Guambler

+0

@Guambler:問題ありません。これは負の数でも有効です。 (または、たとえば-10を-1より大きい値で扱いたいので、本当に大きさを比較していますか?) –

+0

xとyの両方がTMinの場合、エラーが発生します。 – Guambler

1

私はINT_MINからINT_MAXまでのintの全範囲を扱うこの比較的短い解決法をCで提案します。

符号付き整数は2の補数として実装されており、符号付きオーバーフローの不都合な影響はないことが予期されます(未定義の動作になることが知られています)。

#include <stdio.h> 
#include <limits.h> 

int isGreater(int x, int y) 
{ 
    // "x > y" is equivalent to "!(x <= y)", 
    // which is equivalent to "!(y >= x)", 
    // which is equivalent to "!(y - x >= 0)". 
    int nx = ~x + 1; // nx = -x (in 2's complement integer math) 
    int r = y + nx; // r = y - x (ultimately, we're interested in the sign of r, 
        // whether r is negative or not) 

    nx ^= nx & x; // nx contains correct sign of -x (correct for x=INT_MIN too) 

    // r has the wrong sign if there's been an overflow in r = y + nx. 
    // It (the r's sign) has to be inverted in that case. 

    // An overflow occurs when the addends (-x and y) have the same sign 
    // (both are negative or both are non-negative) and their sum's (r's) sign 
    // is the opposite of the addends' sign. 
    r ^= ~(nx^y) & (nx^r); // correcting the sign of r = y - x 

    r >>= (CHAR_BIT * sizeof(int) - 1); // shifting by a compile-time constant 

    return r & 1; // return the sign of y - x 
} 

int testDataSigned[] = 
{ 
    INT_MIN, 
    INT_MIN + 1, 
    -1, 
    0, 
    1, 
    INT_MAX - 1, 
    INT_MAX 
}; 

int main(void) 
{ 
    int i, j; 

    for (j = 0; j < sizeof(testDataSigned)/sizeof(testDataSigned[0]); j++) 
    for (i = 0; i < sizeof(testDataSigned)/sizeof(testDataSigned[0]); i++) 
     printf("%d %s %d\n", 
      testDataSigned[j], 
      ">\0<=" + 2*!isGreater(testDataSigned[j], testDataSigned[i]), 
      testDataSigned[i]); 

    return 0; 
} 

出力:[ド・モルガンの法則](http://en.wikipedia.org/wiki/De_Morgan's_laws)用

-2147483648 <= -2147483648 
-2147483648 <= -2147483647 
-2147483648 <= -1 
-2147483648 <= 0 
-2147483648 <= 1 
-2147483648 <= 2147483646 
-2147483648 <= 2147483647 
-2147483647 > -2147483648 
-2147483647 <= -2147483647 
-2147483647 <= -1 
-2147483647 <= 0 
-2147483647 <= 1 
-2147483647 <= 2147483646 
-2147483647 <= 2147483647 
-1 > -2147483648 
-1 > -2147483647 
-1 <= -1 
-1 <= 0 
-1 <= 1 
-1 <= 2147483646 
-1 <= 2147483647 
0 > -2147483648 
0 > -2147483647 
0 > -1 
0 <= 0 
0 <= 1 
0 <= 2147483646 
0 <= 2147483647 
1 > -2147483648 
1 > -2147483647 
1 > -1 
1 > 0 
1 <= 1 
1 <= 2147483646 
1 <= 2147483647 
2147483646 > -2147483648 
2147483646 > -2147483647 
2147483646 > -1 
2147483646 > 0 
2147483646 > 1 
2147483646 <= 2147483646 
2147483646 <= 2147483647 
2147483647 > -2147483648 
2147483647 > -2147483647 
2147483647 > -1 
2147483647 > 0 
2147483647 > 1 
2147483647 > 2147483646 
2147483647 <= 2147483647 
関連する問題