2015-07-13 552 views
1

據我所知有符號整數的二進制數是11111111111111111111111111111111
並在此基礎上,我試圖讓我的程序最大和最小int值,而無需使用limits.h中頭文件。我運行下面的代碼後,我得到最小值爲-2147483648和最大值爲0.這下面是我的代碼:如何C++代表負值

int MaxInt(){ 
     int MAX = -1; 
     MAX = 0 << ((sizeof(int)*8)-1); 

    return MAX; 
} 


int MinInt(){ 
     int MIN = 0; 
     MIN = 1 << ((sizeof(int)*8)-1); 

    return MIN; 
} 

哪些錯誤我的執行。

+3

出了什麼問題'limits'?你爲什麼重新實施它? – MadScientist

+0

「有符號整數的二進制等價物是11111111111111111111111111111111」 - 這是什麼意思?你想說「簽名有32位」嗎? – anatolyg

+0

是的,這是32位有符號整數@anatolyg – maruf

回答

1

哪些錯誤我的執行

MAX = 0 << ((sizeof(int)*8)-1); 

任何金額移零永遠是零。

+0

您也可以通過移動一定的金額來調用UB。 –

1

這不是特定於C++,而是關於2的補碼形式。在2的補碼中,最重要的比特不僅僅指示符號(該值爲負),而是2的冪(即,對於8比特的2的補數,最高有效比特將代表 - 2^7)。

要設置最負數,只應設置最重要的位。

// Disclaimer: this should work for *most* devices, but it 
    // is device-specific in that I am assuming 2's complement 
    // and I am also assuming that a char is 8-bits. In theory, 
    // you might find a custom chip where this isn't true, 
    // but any popular chip will probably have this behavior: 

    int number_of_digits_in_int = sizeof(int) * 8; 
    int most_significant_digit_index = number_of_digits_in_int - 1; 
    int most_negative_int = 1 << most_significant_digit_index; 

爲了最大的正數,所有正位應設置:

// The complement of 0 has all bits set. This value, by the way 
    // is the same as "-1" in 2s complement form, but writing it 
    // this way for clarity as to its meaning. 
    int all_bits_set = ~(static_cast<int>(0)); 

    // Using an XOR with the most negative integer clears the 
    // most-signficant sign bit, leaving only positive bits. 
    int largest_positive_int = all_bits_set^most_negative_int; 

或者更簡單地說:

// Since the most negative integer has only the negative bit set, 
    // its complement has only the positive bits set. 
    int largest_positive_int = ~most_negative_int; 

正如其他人所指出的,雖然,你應該只使用std::numeric_limits。這也會讓你的代碼更加便攜,甚至在不使用二進制補碼的bizaare設備上工作,例如,更不用說你自己編寫的代碼越少,你犯的錯誤就越少。

+0

而不是'all_bits_set^whatever',使用'〜whatever' - 這樣更清晰。另外,'(int)0'有點尷尬(鑄造沒用)。 – anatolyg

+0

好點,@anatolyg。 –

2

在功能

int MaxInt(){ 
     int MAX = -1; 
     MAX = 0 << ((sizeof(int)*8)-1); 

    return MAX; 
} 
你在第一次分配-1到MAX,然後

重寫了它的價值。所以這個任務沒有意義。

此外,如果要向左移0,那麼您將再次獲得0,取決於您將移位0多長時間。:)

獲得int類型爲2的補內部表示的對象的最大價值的最簡單方法是以下

int MaxInt() 
{ 
    int MAX = -1u >> 1; 
    return MAX; 
} 

或者你可以寫簡單的

int MaxInt() 
{ 
    return -1u >> 1; 
} 

這裏是一個示範程序

#include <iostream> 

constexpr int MaxInt() 
{ 
    return -1u >> 1; 
} 

constexpr int MinInt() 
{ 
    return ~(-1u >> 1); 
} 

int main() 
{ 
    std::cout << MaxInt() << std::endl; 
    std::cout << MinInt() << std::endl; 
} 

程序輸出可能看起來像

2147483647 
-2147483648 
+0

我將如何讓MSB成爲0? – maruf

+0

@馬魯夫對不起,我還沒有理解這個問題。至於我在帖子中顯示的功能,當-1u向右移動一個位置時,符號位被填充爲零。 –

+0

對於負數,MSB位確定的天氣數字是正數或負數,二進制表示-1等於所有位都是1包含MSB,並且我嘗試將MSB位設置爲0,以便數字爲正數 – maruf

2

你的實現有幾個錯誤:

首先,你的-1表示假定int具有二進制補碼32位表示。這不能保證爲int。 (這是爲std::int32_t。)

其次,你認爲intsizeof(int)*8位。這再次不能保證。

在所有這些假設,你仍然有一個錯誤在您的實現:

0 << ((sizeof(int)*8)-1); 

可寫(數學,而不是在C++中)爲:

0 * 2**((sizeof(int)*8)-1) 

現在,如你所知,將0的結果乘以0

假設二進制補碼給出,下面簡單的實現應該工作:

MIN = -1 << ((sizeof(int)*8)-1); 
MAX = ~MIN; 
+0

'MAX =〜MIN'不正確(幾乎正確); '1 <<((sizeof(int)* 8)-1)'調用未定義的行爲('int'溢出);將幾乎總是工作,但不能保證 - 更好地使用'-1'而不是'1'。 – anatolyg

+1

@anatolyg請實際閱讀詳細解釋OPs假設非常錯誤的答案。[鑑於OP的假設,該程序是正確的。](https://ideone.com/hL0QNQ) –

+0

對不起,我錯了'MAX =〜MIN'部分 - 這是絕對可以的。儘管如此,我們不應該依賴'int'溢出的結果,特別是如果它很容易修復(同樣,如果編輯答案,只能刪除downvote)。 – anatolyg