2012-04-14 67 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); 

對於這一點:

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

少了一個運營商。

+3

+1 [德·摩根定律(http://en.wikipedia.org/wiki/De_Morgan's_laws):) – ulmangt 2012-04-14 04:52:33

+1

這是完美的謝謝! – Guambler 2012-04-14 05:00:49

2

這條線:

return 0 | (~equal & check2);

可以簡化爲:

return (~equal & check2);

(逐位or0不具有任何影響)

4

check1僅僅是一個xnor。你爲什麼不替換此:

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

與此:

int check1 = ~(xSign^ySign); 

你的版本5個運算符,該礦擁有2

請注意,您的代碼將是,如果你更美觀使用這個:

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,並檢查結果是否爲負。爲了保持至少一點挑戰,我假設我們不能直接進行減法,所以我們必須自己否定數字(使用二進制補碼,所以翻轉位並添加一個)。

五個操作員 - 如果您包含演員,則爲六個操作員。值得注意的一點是:你自己計算的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是正面的還是負面的。我還檢查了這兩個數字是否相等以涵蓋所有基地 – Guambler 2012-04-14 06:22:28

+0

@Guambler:不是問題。這適用於負數。 (或者你想對待,例如,-10大於-1,所以你真的比較大小?) – 2012-04-14 06:24:01

+0

當x和y都是TMin時,我會收到錯誤。 – Guambler 2012-04-14 06:27:17

1

我在C中提出了這個相對較短的解決方案,該解決方案處理從INT_MININT_MAX的整個範圍的整數。

它期望有符號整數實現爲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; 
} 

輸出:

-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