2010-09-13 37 views
1

假設你有2個數字:如何表示使用位運算符否定,C

int x = 1; 
int y = 2; 

使用位運算符,我怎麼能代表x-y

+2

作業...? – kennytm 2010-09-13 18:45:34

+0

號我只是通過一本書閱讀,嘗試不同的東西 – JAM 2010-09-13 18:48:11

+1

相關:[*減號沒有減號*](http://stackoverflow.com/questions/700410/subtraction-without-minus-sign) – kennytm 2010-09-13 18:51:00

回答

5

當比較兩個數字AB的位時,有三種可能性。以下假定無符號數字。

  1. A == B:所有位都相同
  2. A > B:這兩個數字之間的不同之最顯著位在A設置,而不是在B
  3. A < B:這之間的區別,最顯著位這兩個數字在B設置,而不是在A

代碼可能類似於以下

int getDifType(uint32_t A, uint32_t B) 
{ 
    uint32_t bitMask = 0x8000000; 
    // From MSB to LSB 
    for (bitMask = 0x80000000; 0 != bitMask; bitMask >>= 1) 
    { 
    if (A & bitMask != B & bitMask) 
     return (A & bitMask) - (B & bitMask); 
    } 
    // No difference found 
    return 0; 
} 
+0

這個函數會在64位機器上接受int嗎? – 2010-09-13 19:12:42

+0

@crypto,參數和變量都是32位類型,所以沒關係。 – 2010-09-13 20:30:28

3

您需要閱讀大約two's complement算術。加法,減法,否定,符號測試以及其他一切都是由硬件使用按位運算來完成的,所以你可以在你的C程序中完成它。上面的維基百科鏈接應該教會你需要知道的一切來解決你的問題。

1

您的第一步是僅使用按位運算符來實現加法。之後,一切都應該很容易。從小開始 - 你需要做些什麼來實現00 + 00,01 + 01等?從那裏出發。

1

您需要從最重要的一端開始檢查以查找數字是否較大。該邏輯僅適用於非負整數。

int x,y; 
//get x & y 
unsigned int mask=1;   // make the mask 000..0001 
mask=mask<<(8*sizeoF(int)-1); // make the mask 1000..000 

while(mask!=0)    
{ 
if(x & mask > y & mask)   
{printf("x greater");break;} 
else if(y & mask > x & mask) 
{printf("y greater");break;} 
mask=mask>>1;     // shift 1 in mask to the right 
} 
1

比較從左到右的位,尋找不同的最左邊的位。假設一臺機器是二進制補碼,最高位確定符號,並且與其他位相比將具有翻轉的比較意義。這應該適用於任何兩個補碼機器:

int compare(int x, int y) { 
    unsigned int mask = ~0U - (~0U >> 1); // select left-most bit 
    if (x & mask && ~y & mask) 
    return -1; // x < 0 and y >= 0, therefore y > x 
    else if (~x & mask && y & mask) 
    return 1; // x >= 0 and y < 0, therefore x > y 
    for (; mask; mask >>= 1) { 
    if (x & mask && ~y & mask) 
     return 1; 
    else if (~x & mask && y & mask) 
     return -1; 
    } 
    return 0; 
} 

[請注意,這在技術上是不便攜的。 C不保證有符號算術是二進制補碼。但是你會很難在現代機器上找到一個具有不同行爲的C實現。]

要明白爲什麼這會起作用,首先考慮比較兩個無符號數13d = 1101b和11d = 1011b。 (爲簡潔起見,我假設爲4位字的大小)。最左邊的不同位是左邊的第二位,前者已設置,而另一位不是。因此前者的數字更大。應該很清楚,這個原則適用於所有的無符號數字。

現在,考慮兩個補碼數。您通過補充位並添加一個來取消數字。因此,-1d = 1111b,-2d = 1110b,-3d = 1101b,-4d = 1100b等。您可以看到可以比較兩個負數,就好像它們是無符號的。同樣,兩個非負數也可以像無符號一樣進行比較。只有當符號不同時,我們纔會考慮它們 - 但如果它們不同,則比較是微不足道的!

+1

正如R在迴應我關於表示的評論時正確地指出的那樣,您可以始終投射到'unsigned int' - 演員陣容保證使用模算術,這有效地確保了在比特級上的二進制補碼錶示。 – 2010-09-13 23:55:01