2013-03-05 90 views
3

我是編程新手,想讓我的程序獲得一個給定的數字,加倍,然後在用戶輸入多天的情況下繼續加倍。我做了這個循環,它的工作原理,但最終的數字是負面的。我不知道如何阻止它出現負面情況,並希望得到任何幫助。Printf出現負數

int main(void) 
{ 

    int d; 
    int s; 
    float a; 

    do 
    { 
     printf ("Please enter the amount of days in the month: "); 
     d = GetInt(); 
    } while (d > 31 || d < 28); 

    do 
    { 
     printf("Please enter the amount of pennies you start will start with: "); 
     s = GetInt(); 
    } while(s < 0); 

    do 
    {  
     s = s * 2; 
     d = d - 1; 
     a = s/100.0; 
     printf("%f\n", a); 

    } while(d > 0); 

    return 0; 
} 
+7

's'和'd'從哪裏來?他們的初始價值是什麼? – 2013-03-05 21:18:33

+0

知道s,d和a是什麼也是有幫助的。他們是32位整數嗎? – 2013-03-05 21:20:17

+1

發佈「相關」代碼 - 所有值的定義和初始值至少爲 – KevinDTimm 2013-03-05 21:24:49

回答

4

的問題是在這裏:

s=s*2; 

(雖然你應該確保循環之前總是初始化變量,例如s=0

整數沒有當數量大於存儲類型時特殊值,所以他們overflow

下面是可能發生的一個例子。想象一下,我們將整數存儲爲一系列4位,其中第一位表示數字爲負數。然後如果我們開始在我們的系統計算,我們得到如下:

0000 = 0 
0001 = 1 
0010 = 2 
0011 = 3 
0100 = 4 
0101 = 5 
0110 = 6 
0111 = 7 
1000 = -0 
1001 = -1 
1010 = -2 

所以你可以看到,數字不斷在計算機內部增長,但他們翻譯時,最顯著位翻轉突然變成負上。

計算機使用各種不同的方案來存儲負數,但Two's Complement是常見的。它比我在這裏用來解釋事物的系統更聰明,但是要點仍然是一樣的:當數字變得太大時,它們變成負面的。在int的情況下,交叉點往往是當你打2^31,或2147483648

一種解決方法是使用unsigned int,大致增加一倍,你可以代表人數最多的,還是longlong longunsigned long,或unsigned long long。記住,這不會解決你的問題,它只會給你更大的數字,你可以在問題出現之前處理。

您可以使用limits.h頭文件找到最大可用值;對於int它是INT_MAX

+0

採用32位數字,'無符號int'實際上解決OP的問題,因爲沒有一個月的時間超過31天;)(但這是一個特殊的情況。) – 2013-03-05 22:47:15

1
2^31 = 2147483648 

如果超過30天,您將溢出一個整數,即使以1便士開始,並將該值加倍。如果你從更大數量的便士開始,你會很快溢出。

當一個整數溢出時,它顯示爲負值。根據下面的建議,這是未定義的行爲。這是程序員使用的術語,而新人們不太瞭解。 C標準的

+0

你錯了;當表達式產生的數字太大而無法在其類型中表示時,行爲是未定義的。 'int x = INT_MAX + 1;',例如,是未定義的行爲。談論「常見」這一點並不鼓勵「便攜式」解決方案。 – Sebivor 2013-03-05 23:27:27

+0

@modifiable lvalue - 你完全正確。但是這並不表示這是一個粗魯的「這是UB」對於一個新手來說是一個很好的答案。這根本不好。因爲這會讓某人不知情,於是被迫查找未定義的行爲並想知道它的真正含義。在這種情況下,整數溢出吹走變量的內容,所以你會得到垃圾。這就是UB的意思 - 用簡單的語言:任何事情都可能發生。正如他們所說,這個程序「甚至沒有錯」。正如字符串理論家所說...... – 2013-03-05 23:41:42

+0

...所以你明白了爲什麼「當一個整數溢出時,它顯示爲負值」屬於一個*錯誤的答案*,但你仍然決定。在現實世界中,這種未定義的行爲具有飽和,信號投擲和包裹(這是你描述的行爲)的效果。 「一個好的答案」是否包含誤導性信息? – Sebivor 2013-03-06 02:47:49

1

第6.5p5:

如果 表達的評價(即,如果該結果不是數學上不表示的值的範圍限定或 期間發生的異常條件對於其類型),行爲 未定義。

它說的是,任何int表達比INT_MAXINT_MIN時,或多或少會造成問題。這些問題沒有定義,所以你不能處理它們;最好避免這樣的事情。就你的情況而言,如上所述,計算包裝爲負值。然而,這不是必需的。也許如果你要在不同的系統上用不同的編譯器編譯和運行它,你的程序可能會崩潰,或者它看起來像預期的那樣工作,不知何故在有限的存儲空間中代表無限的值,或者可能是雞幾分鐘左右無頭奔跑......誰知道?

您可以通過仔細選擇具有更廣泛的範圍內,如被覆蓋在其他的答案類型,並執行對您輸入的值上限,以便沒有溢出可能避免這個問題。另一種方法是使用任意精度的運算庫,例如GNU MP Bignum,它們不應該溢出。

+0

現在,這遠遠超出您的意見。你的評論等於'這是UB',所以拿它或離開它。繼續做這樣的回答:+1。我們有太多短小,無用,傲慢甚至討厭的評論。其中沒有任何地方可以得到任何人。有一點:完全正確和溝通是有區別的,這篇文章展示了溝通,你的評論沒有。 IMO。 – 2013-03-06 04:39:07