大きな階乗を計算するとき、なぜ負の数を取得するのですか?

StackOverflow https://stackoverflow.com/questions/236335

  •  04-07-2019
  •  | 
  •  

質問

それで、簡単な手順で、階乗数を計算します。コードは次のとおりです。

int calcFactorial(int num)
{
    int total = 1;

    if (num == 0)
    {
        return 0;
    }

    for (num; num > 0; num--)
    {
        total *= num;
    }

    return total;
}

現在、これはほとんどの数字でうまく機能します(確かにより速く、よりエレガントなソリューションがありますが、これは私にとってはうまくいきます)。しかし、それを250などのより大きな数字を入力するときは、率直に言えば、がらくたです。さて、最初のいくつかの階乗の「ビット」は250の場合は、参照用に{250、62250、15126750、15438000、3813186000}です。

私のコードは{250、62250、15126750、15438000、 -481781296 }を吐き出しますが、明らかにオフです。私の最初の疑いは、おそらく32ビット整数の制限に違反したことでしたが、2 ^ 32が4294967296であることを考えると、そうは思いません。私が考えることができる唯一のことは、おそらくそれが署名の32ビット制限に違反しているということですが、この種のことを考えるべきではないでしょうか?署名されることが問題である場合、整数を符号なしにすることでこれを解決できますが、これは一時的な解決策にすぎません。

だから、私の問題は署名された制限ですか?もしそうなら、再びこの問題に出くわすことなく大きな数を計算するために何ができますか?

役に立ちましたか?

解決

2 ^ 32では、符号付き整数の制限はありません。

符号付き整数の制限は、実際には 2147483647 です。 (MSツールを使用してWindowsで開発している場合、他のツールスイート/プラットフォームには、おそらく同様の独自の制限があります。)

C ++多数ライブラリこのようなライブラリが必要です。

他のヒント

他のコメントに加えて、コードの2つの重大なバグを指摘したいと思います。

  • 負の数に対するガードはありません。
  • ゼロの階乗はゼロではなく1です。

はい、制限に達しました。 C ++のintは、定義により署名されています。そして、ええと、いや、C ++は決して考えません。何かをするように言うと、明らかに間違っていてもそれをします。

多数のライブラリを使用することを検討してください。 C ++にはそれらの多くがあります。

署名済みまたは未署名を指定しない場合、デフォルトは署名済みです。これは、コンパイラのコマンドラインスイッチを使用して変更できます。

C(またはC ++)は非常に低レベルの言語であり、指示どおりに実行することを忘れないでください。この値を符号付き整数に格納するように指示すると、それが実行されます。プログラマとしてのあなたは、それがいつ問題になるかを把握する必要があります。言語の仕事ではありません。

Windowsの計算機( Start-Run-Calc )から次のことがわかります

hex (3813186000) =         E34899D0
hex (-481781296) = FFFFFFFFE34899D0

はい、原因は署名された制限です。階乗は定義上正の値のみであり、正の数値に対してのみ計算できるため、引数と戻り値の両方は符号なしの数値でなければなりません。 (誰もがforループで int i = 0 を使用することを知っているので、私もそうします。ただし、値が負にならない場合は常に符号なし変数を使用する必要があります。

階乗の一般的な問題は、それらが非常に大きな数を簡単に生成できることです。フロートを使用して精度を犠牲にすることもできますが、整数オーバーフローの問題は回避できます。

ああ、私が上で書いたように、あなたはそれを符号なしのフロートにするべきです;-)

オーバーフローの問題があります。階乗は整数の制限を簡単に超えることができます。 doubleを返すように関数を変更することもできますが、それではもう少し余裕ができます。アプリケーションでは、最終結果がdoubleに収まるが中間ステップが収まらないような、階乗と非常に小さい数の乗算が必要になることがよくあります。この状況を処理する方法を説明する記事を次に示します。 http://www.johndcook.com/blog/2008/04/24/how-to-calculate-binomial-probabilities/

よく覚えている場合:

unsigned short int = max 65535

unsigned int = max 4294967295

unsigned long =最大4294967295

unsigned long long(Int64)=最大18446744073709551615

編集されたソース:

Int / Long Max値

最新のコンパイラ変数

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top