2017-10-07 43 views
1

我想學習一些C編程,並測試我的基本技能,我正在計算一個簡單的計算因子。但是,不給出120的正確答案5的階乘,它給出了-1899959296。怎麼了?這裏是我的代碼如下:爲什麼這個階乘計算不正確?

#include <stdio.h> 

int factorial(int x) 
{ 
    int i; 
    for(i=1; i < x; i++) 
     x *= i; 
    return x; 
} 

int main() 
{ 
    int a = 5, b; 
    b = factorial(a); 
    printf("The factorial of %d is %d \n", a, b); 
    return 0; 
} 

在此先感謝!

+0

假裝你是一臺計算機,並嘗試一步一步運行它,x = 2(或3)。或者,在調試器中運行它。 – user31264

+5

請參閱[**如何調試小程序**](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)並與鴨子交談...真的,它幫助':)' –

+1

作爲提示:看看循環綁定。 – templatetypedef

回答

3

您的問題是功能factorial()正在不斷修改x。對於初始爲3或更多的x中的任何一個,x將繼續增加,因此循環將繼續運行。

請考慮如果您致電fact(3)

使用x = 3調用該函數。與i = 1循環的第一次迭代將乘以x1。所以x仍然會有價值3ii將增加到2,這小於3,所以下一次迭代開始。

該循環的第二次迭代將乘以x,2,給出6的結果。 i增加到3,這小於6,所以下一次迭代開始。

第三次迭代將乘以x乘以3,得出18的結果。 i增加到4,這小於18,所以下一次迭代開始。

注意上面的模式.....結束條件是i < x。每個迭代中增加ix乘以i。這意味着xi確實增加得快得多,這意味着i < x總是如此。

好吧......最終邏輯崩潰了。

最終x會溢出 - 將其乘以i的結果將產生超過可存儲在int中的結果的結果。溢出int的結果是未定義的.....在這一點上可能發生任何事情。

將上面的描述與如果要求計算3的因子時應該執行的操作相比較。你會做類似的步驟嗎?可能不會。

3
int factorial(int x) 
    { 
     int i; 
     int count =x; 
     for(i=1; i < count ; i++) 
      x *= i; 
     return x; 
    } 

修改成這樣。你的問題是與循環計數..由於x的值正在改變循環可能會變得無限..

1

C)你正在使用X作爲上界爲您的for循環i < x

B)你還對每個循環x *= i增加X幾乎成倍,您的循環將無法正常工作。

你可能已經注意到你得到一個負數。循環完全退出的原因是,您選擇將x輸入爲32位有符號整數(默認爲int) - 處理器以二進制方式工作:因此,一旦以高於僅32位的實際可能值進行工作,它仍然試圖做數學,但它會丟失數據並回到負數。所以一旦x循環回去併成爲負數,然後i > x和循環退出。

這裏:http://tpcg.io/8sX5ls

+0

我不確定爲什麼您認爲給定a)符號位/進位標誌的基本性質,也不b)由用戶輸出證明。 –

+0

嘿嘿,我試圖通過回答問題來獲得我的老師徽章,但是它很難,因爲總是有這麼多其他答案XD –

1

的錯誤是在for,一個數的階乘是N * N-1 * ... * N-(N-1),所以解決這個問題,僅僅以x - 1開始索引並將其減1,直到變爲1,對不起我的英文不好,我希望你明白我的意思。

這裏就是答案:

for (i = x - 1; i > 1; --i) 
     x *= i; 

只是爲了解釋爲什麼負數,首先我們必須瞭解它被宣佈爲for會發生什麼。

for(i=1; i < x; i++) 
     x *= i; 

正如我們所看到的情況爲它在循環繼續爲i < x,但在它被分配到xx * ix * = i or x = x * i)的值,所以x沒有固定值,並且總是不斷增加, i以小於x的速度增加,因爲i總是添加到1(i ++, i + = 1 or i = i + 1),這導致x無法訪問,則for將處於無限循環。

但每一種類型都有其範圍,int爲4個字節,因此32位,會發生什麼情況是,當x超過其著名的整數溢出此範圍內有這種時候,這就是爲什麼它的值是負的,那麼for的條件變爲false,然後for停止。

我們必須記住,一個數字以二進制形式表示在內存中,最後一個二進制數表示數字是正數還是負數,0表示正數,1表示負數,當發生整數溢出時,最後一個數字更改爲1,使其如此消極。

爲了更好地理解這裏有一些鏈接,可以幫助:

https://en.wikipedia.org/wiki/Two%27s_complement

https://en.wikipedia.org/wiki/Integer_overflow

+0

你能解釋OPs代碼導致的非常不利的結果嗎? – Yunnosch

+0

老兄,答案很長,我不能把它放在這裏,所以我編輯了我以前的答案,回答你的問題,好吧。 –

+0

這就是改善答案的意圖。看起來你已經得到了讚賞。 – Yunnosch