数値66の階乗値を取得しようとしていますが、メソッドの結果は0になります。しかし、 5の階乗を取得しようとすると、出力120になります。誰か教えてもらえますか?
public static int factorial(int n)
{
if (n == 1)
return n;
return n * factorial(n - 1);
}
確かに-階乗は非常に大きく、非常に速くなります。あなたはintの境界を非常に速くオーバーフローしています...そしてある時点で、オーバーフローを0にするのに十分な係数を掛けて、値を永久に0に保ちます。
グーグルのクイック検索によると、66階乗は5.44344939×10 92int
であり、これは処理できる量よりもかなり多く、さらにはlong
またはdecimal
です。あなたはそれを処理することができますdouble
-あなたは膨大な量の精度を失うでしょう、そしてそれは本当にすぐに蓄積するでしょう、しかし少なくともそれはオーバーフローしません...
66!に適合しませんint
。を使用しBigInteger
ます。
メソッドがオーバーフローします。次の例を参照してください。
static void Main(string[] args)
{
Console.WriteLine(factorial(66));
}
public static int factorial(int n)
{
if (n == 1)
return n;
var result = n * factorial(n - 1);
Console.WriteLine("{0} : {1}", n, result);
return result;
}
この例では、各反復の結果が出力されます。
ある時点で結果がになり0
、これはその時点以降のすべての反復がになることを意味しますn * 0
。
を使ってみることができますBigInteger
。これにより、正しい結果が得られます。C#での階乗の計算には、これに関する詳細情報が含まれています。
問題は、66の階乗がに収まるように大きくなる方法であるということint
です。に収まるように大きくすることもできると思いますlong
。
例としてfactorial(20)
、2432902008176640000
50の階乗は3.0414093202×1064であり、intに含めることができるものをすでに実行しています。
long
またはこれに使用BigInteger
します。
数値オーバーフローが発生します、66!〜= 5e92は、int
缶が処理できるよりもはるかに大きいです。また、階乗はforループを使用してより適切に計算されます。
階乗が整数に収まる最大の数は約13または14です...longに切り替えると、正しく思い出せば18または19になります。大きな数の調停を希望する場合は、独自の大きな算術ライブラリを作成するか、既存のライブラリを使用する必要があります:)