1

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

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

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

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

    return total;
}

さて、これはほとんどの数でうまく機能します(より迅速でエレガントなソリューションは確かにありますが、これは私にとってはうまくいきます)。ただし、250 などの大きな数値を入力すると、率直に言って、クラップアウトします。ここで、参考までに、250 の最初の 2 つの階乗 "ビット" は { 250, 62250, 15126750, 15438000, 3813186000 } です。

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

それで、私の問題は署名された制限ですか?もしそうなら、この問題に再び遭遇することなく、大きな数を計算するにはどうすればよいですか (私は少し前に作成した「LargeInteger」クラスを持っていますが)、この問題に再び遭遇することはありませんか?

4

6 に答える 6

21

2^32 は、符号付き整数の制限を与えません。

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

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

于 2008-10-25T12:41:50.890 に答える
13

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

  • 負の数に対するガードはありません。
  • ゼロの階乗はゼロではなく 1 です。
于 2008-10-25T12:46:25.903 に答える
9

はい、限界に達しました。C++ の int は、定義上、signed です。そして、ええと、いいえ、C++ は決して考えません。何かをするように指示すると、明らかに間違っていても実行します。

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

于 2008-10-25T12:43:19.670 に答える
4

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

C (または C++) は非常に低レベルの言語であり、指示どおりに実行することを覚えておいてください。この値を signed int に格納するように指示すると、それが実行されます。あなたはプログラマーとして、それがいつ問題になるかを理解する必要があります。それは言語の仕事ではありません。

于 2008-10-25T12:44:36.907 に答える
1

私の Windows 電卓 ( Start-Run-Calc ) は、それを教えてくれます

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

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

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

ああ、私が上に書いたことによると、それを unsigned float にするべきです ;-)

于 2008-10-25T12:50:20.183 に答える
-3

私がよく覚えていれば:

unsigned short int = 最大 65535

符号なし整数 = 最大 4294967295

unsigned long = 最大 4294967295

unsigned long long (Int64)= 最大 18446744073709551615

編集されたソース:

Int/Long 最大値

最新のコンパイラ変数

于 2008-10-25T12:42:38.393 に答える