2012-03-15 5 views
4

に私は、Javaのため、この階乗のプログラムを使用してきた。しかし階乗は、Java

public static long factorial(int a) { 

    if(a<1) { 
     return 1; 
    } 
    long result=1; 
    long x=a; 
    while(x>1) { 
     result*=x;      
     x--; 
    } 
    return result; 
} 

、それは「休憩」とそれがために負の数を返す25の階乗の後に負の数を返すように思えます「0」を返します。

私はこれを引き起こしている何か間違っていますか?

+3

あなたが保持できる最大数とint型について何を知っている、これはあなたの宿題ですか? –

+0

これは私の宿題ではなく、これは私の楽しい仕事です:)(私はオタクです)。私は宿題のためにこのような助けを求めることは決してありません。私はintが保持できる最大の数について何も知らない。私はドキュメントでそれを調べます。 – Toby

+0

@ dann.dev: 'int'とは何ですか? – SLaks

答えて

7

longがオーバーフローしました。
代わりにBigIntegerを使用してください。

+1

はい:http://membres.multimania.fr/rsirdey/facttabl.htm – duffymo

+0

ニースのページは、しばらくしてもめまいになります。 –

+0

私はBigIntegerを使用していくつかの問題を抱えていましたが、返す前にBigIntegerにlongを変換しますか? – Toby

3

25! Long.MAX_VALUEより大きく...

0

もう少し素朴で非整数の場合に有効なもう1つのアプローチは、ガンマ関数の自然対数を使用することです。

http://www.iro.umontreal.ca/~simardr/ssj/doc/html/umontreal/iro/lecuyer/util/Num.html

あなたはこの実装を使用してに固執しなければならない場合、私はあなたがメモ化を検討することをお勧めします。なぜ値を再計算するのですか?いったん持っていれば、それにぶら下がり、繰り返しの要求でそれを渡してください。

+0

それは役に立たないでしょう。それでもオーバーフローします。 – SLaks

+0

最終的には、長い意志よりもずっと長い間、ダブルがハングします。そして自然のログはそれをも遅らせるでしょう。コンビナトリアル計算に役立ちます:自然のログを加算したり減算したりするだけです。 – duffymo

4

25! = 15511210043330985984000000

Javaで長いの最大値は、2^63-1 = 9223372036854775807source)です。

25! Javaで長時間保存できる最大値の約1.7 * 10^6です。代わりにBigIntegerを使用してください。

0

、私はタイトルが整数を指し知っているが、原理は要するにint型のため、長い間、ダブルなど

スタンドあなたはそれの上に行くときに、プリミティブデータ型は、最大値を持って、それをhttp://en.wikipedia.org/wiki/Integer_overflowをチェックアウトarounをラップし、再び開始します。あなたが本当にそれについて怪しげにしたいなら、それを完全に理解するためにバイナリの追加について学んでください。

1

JLSによれば、オーバーフロー(およびアンダーフロー)はサイレントであるため、結果は「驚き」でした。

は、次の2つの選択肢があります正確性が必要とされていない場合、正確な答えが必要な場合

  • を、(たとえそれがオーバーフローするものの、過去170!doubleを使用して、BigIntegerの
  • を使用
0

あなたが欠けているものは次のとおりです。符号付き整数プリミティブ型(short、int、longなど)が表すことができる符号付き値よりもインクリメントされると、その符号ビットを反転しようとします。想定する数字の符号を示すのに使用されるd。符号ビットの1は負の値を示します。この現象を整数オーバーフローといいます。

疑似3ビット符号付きプリミティブデータ型を考えてみましょう(比較のために、Java longは64ビットです)。それは-4と3の間の数字を表すことができます。

3、3ビットの数を表すことができます最大の正の値は、次のようになります。011

011に1を追加し、あなたが得る:100

(番号部分は、符号部にオーバーフロー) 100の小数点以下のバージョンは-4

ですが、長さの容量を扱う場合は、数を数える必要があります。したがって、指定されていない非最適化で定義されている最大の数を簡単に判別できますシーケンス(この場合、階乗):

long n = 1; 
while (factorial(n) > 0) { 
    System.out.println("factorial of " + n++ + " can fit in a long!"); 
} 

これは無限ループでなければならないようですが、そうではありません。最終的に、階乗(n)は整数のオーバーフローのために負の値を返します。 これはあなたに次のような出力が得られます:

factorial of 1 can fit in a long! 
factorial of 2 can fit in a long! 
factorial of 3 can fit in a long! 
factorial of 4 can fit in a long! 
factorial of 5 can fit in a long! 
factorial of 6 can fit in a long! 
factorial of 7 can fit in a long! 
factorial of 8 can fit in a long! 
factorial of 9 can fit in a long! 
factorial of 10 can fit in a long! 
factorial of 11 can fit in a long! 
factorial of 12 can fit in a long! 
factorial of 13 can fit in a long! 
factorial of 14 can fit in a long! 
factorial of 15 can fit in a long! 
factorial of 16 can fit in a long! 
factorial of 17 can fit in a long! 
factorial of 18 can fit in a long! 
factorial of 19 can fit in a long! 
factorial of 20 can fit in a long!