4

私は現在、微積分を行っており、階乗10の結果が得られる簡単なプログラムを作成することを考えていました。テスト中に、5回目の反復後に誤った結果が得られていることに気付きました。ただし、最初の4回の反復は正しいです。

public class Factorial
{
    public static void main(String[] args)
    {

        int x = 1;
        int factorial;

        for(int n = 10; n!=1; n--)
        {

            factorial = n*(n-1);
            x = x * factorial;
            System.out.printf("%d ", x);

        }

    }//end of class main
}//end of class factorial

なぜ負の値になるのですか

4

4 に答える 4

9

これは整数のオーバーフローの問題です。の代わりにlongまたはを使用します。(@Dunesが示唆しているように、理論的にはオーバーフローすることはないため、非常に大きな数で作業する場合に最善の策があります)unsigned longintBigInteger

基本的な考え方は、signed intは、間の数値を-2,147,483,648 to 2,147,483,647格納し、それらはバイナリビットとして格納されるというものです(コンピューター内のすべての情報は1'sおよび0'sとして格納されます)

正の数は0最上位ビットに格納され、負の数は1最上位ビットに格納されます。2進表現で正の数が大きくなりすぎると、数字が符号付きビットに引き継がれ、正の数が負の2進表現に変わります。

次に、階乗がunsigned int格納できる値よりも大きくなると、階乗は「ラップアラウンド」し、最も重要な(符号付き)ビットからのキャリーオーバーを失います。そのため、正と負の値が交互に現れるパターンが見られます。出力。

于 2012-12-07T23:25:49.163 に答える
7

タイプの容量int(2,147,483,647)を超えているため、結果は最小int値に戻ります。long代わりに使用してみてください。

そうは言っても、現在使用している方法では正しい答えは得られません。実際には、現在計算中10! ^ 2です。

なぜ物事を複雑にするのですか?あなたは簡単にこのようなことをすることができます:

long x = 1L;

for(int n = 1; n < 10; n++)
{
    x *= n;
    System.out.println(x);
}
1
2
6
24
120
720
5040
40320
362880

これは、に達するまで連続する階乗を示します10!

また、他の人が述べているように、longサポートできる値よりも大きい値が必要な場合BigIntegerは、任意精度をサポートするを使用する必要があります。

于 2012-12-07T23:26:07.057 に答える
3

階乗の式が正しくありません。あなたが持っているものはこれです:

  1. ステップ1:n *(n-1)= 10 * 9 = 90 => x = 1 * 90 = 90
  2. ステップ2:n *(n-1)= 9 * 8 = 72 => x = 90 * 72 = 6480または、次のようになります:10 * 9 * 8 => 720

しかし、間違った結果は、他の人が指摘したように、int型の最大値に達したという事実から来ています

あなたのコードは

public class Factorial
{
    public static void main(String[] args)
    {
        double factorial = 1;

        for(int n = factorial; n>=1; n--)
        {
            factorial = factorial * n;
            System.out.printf("%d ", factorial );

        }
    }
}
于 2012-12-07T23:27:28.277 に答える
2

他の回答がオーバーフローについて言及していることに加えて、階乗アルゴリズムも正しくありません。10!計算する必要があります10*9*8*7*6*5*4*3*2*1、あなたはやっています(10*9)*(9*8)*(8*7)*(7*6)*...

ループを次のように変更してみてください。

int x = 1;
for(int n = 10; n > 1 ; n--)
{
    x = x * n;
    System.out.printf("%d ", x);
}

より高い数値の階乗を計算しようとすると、最終的にオーバーフローしますがint、10の階乗を計算するには十分な大きさです。

于 2012-12-07T23:31:36.557 に答える