簡體   English   中英

簡單的C ++階乘程序

[英]Simple C++ factorial program

作為家庭作業,我需要一個讀取非負整數的程序,並計算並打印其階乘。 到目前為止我編寫了代碼,但如果我嘗試輸入50! 結果為0.它適用於較小的數字。 任何幫助將非常感激。

#include <iostream>

using namespace std;

int main()
{
    int counter = 1;
    int number;

    cout << "Please enter a number: ";
    cin >> number;

    int factorial = number;
    while (counter != number)
    {
        factorial = factorial * (number - counter);
        counter++;

    }

    cout << "The factorial of " << number << "! is: " << factorial << endl;
    return 0;
}

50! 30414093201713378043612608166064768844377641568960512000000000000 ,對於一個int來說太大了。 由於整數溢出,結果為0。

如果要計算大因子,則需要使用一些BigInteger類。 看看這個: 線程

已經有了一些答案。 然而,他們都缺乏提供一些(imho)重要事實:

無論您選擇多大的結果類型,您的程序將能夠計算的內容總是有限制的。

在正常的口袋計算器69! 是他們可以顯示的最大因子(因為它是具有兩位數指數的最大因子)。 要求更大的東西只會導致錯誤或NaN。 實際上這完全沒問題,因為在實踐中你很少需要具有完美精度的巨大因子。 通常可以使用Stirlings近似或使用其他技巧來避免冗長的計算(順便說一下69!對於袖珍計算器來說也是一個不錯的基准,因為它可能在慢速計算器上花費幾秒鍾)。

結論 :對於合理的輸入,您的代碼非常好。 如果你真的需要尋求更高的階乘,有辦法,但我想你的任務並不是真的要求它。 而且,無論你怎么做,你總是達到極限。 因此,為了使您的代碼“無bug”,我會添加類似的東西

assert(number < 50 && "Sorry, this number is too big");

在計算之前。

選擇較大范圍的數據類型,不超過存儲在變量'factorial'中的值

你應該聲明它, **long long int factorial = number ;**

現在,它顯示為零,因為int(此處為signed)因此對於將int數據類型存儲為2byte的系統,其范圍從-32568到+32567。 在修飾符“long long”的幫助下,實際上將其存儲字節增加到8字節,從而產生更大的范圍。

現在,如果要存儲在任何變量中的值超出其范圍,則它通過開始從最小范圍(這里是-32568)存儲的值來執行循環旋轉。

而你也可以使用**unsigned long long int factorial = number ;**甚至可以使它的范圍更大。 由於無符號將計算其負范圍與正范圍,從而導致更大的正范圍。

在類或結構中嘗試雙或長數據類型。 您還必須相應地修改您的代碼。

Factorial只會產生瘋狂的大數字。 您可以嘗試更廣泛或可能更寬的數據類型(如long ),但這只會推遲問題。 在某些時候失敗。 也許在51! ,也許是60! 我們甚至不談1000! 這就是階乘的本質。

當然,專門的大數字圖書館可以大大緩解這個問題。 但他們不是初學者的東西。

但是,您可以做的就是安全地找出您的程序是否達到計算機的限制,如果是這種情況則打印錯誤消息。 C ++提供了一種名為std::numeric_limits的機制,它告訴您數據類型可以表示的最大可能值。

這是一個基於您的代碼的簡單示例:

#include <iostream>
#include <limits> // needed for std::numeric_limits

using namespace std;

int main()
{
    int counter = 1;
    int number;

    cout << "Please enter a number: ";
    cin >> number;

    int factorial = number;
    while (counter != number)
    {
        if (std::numeric_limits<int>::max() / factorial < (number - counter)) {
            std::cout << "cannot handle such large numbers\n";
            return 0;
        }       
        factorial = factorial * (number - counter);
        counter++;

    }

    cout << "The factorial of " << number << "! is: " << factorial << endl;
    return 0;
}

一旦檢測到錯誤條件,將會發生什么並不重要,而是如何檢測它:

std::numeric_limits<int>::max() / factorial < (number - counter)

這可以防止整數溢出。 它在數學上等同於:

std::numeric_limits<int>::max() < factorial * (number - counter) // wrong!

但是,后一版本顯然不起作用,因為factorial * (number - counter)可能已經產生溢出。 通過將右側的乘法轉換為左側的除法,您可以優雅地避免該問題。


順便說一句,如果用戶輸入一個非常大的數字,所有這些仍然沒有好處。 因此,您應該在使用number之前檢查std::cin的狀態,如果輸入無法解釋為int ,則同樣打印錯誤消息。 這使您的程序更加健壯。 如果有人輸入大數字,它不會簡單地崩潰或產生無意義的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM