2016-07-26 5 views
1

非常に大きな階乗を計算する必要がありますが、正確でなければなりません。私は近似を使うことはできません。大きな階乗を正確に計算する

私は1,000,000,000を得たいと思っていますが、かなり遅いです。これまではパフォーマンスを少し改善しましたが、まだ十分ではありません。

 BigInteger Factor100 = BigInteger.One; 
     BigInteger Factor10000 = BigInteger.One; 
     Status = "Factorising"; 
     for (i++; i <= StartN; i++) 
     { 
      if (Worker.CancellationPending) 
      { 
       e.Cancel = true; 
       break; 
      } 

      if (i % 10000 == 0) 
      { 
       Factor100 = Factor100 * i; 
       Factor10000 = Factor10000 * Factor100; 
       iFactorial = iFactorial * Factor10000; 
       Factor100 = BigInteger.One; 
       Factor10000 = BigInteger.One; 
      } 
      else if (i % 100 == 0) 
      { 
       Factor100 = Factor100 * i; 
       Factor10000 = Factor10000 * Factor100; 
       Factor100 = BigInteger.One; 
      } 
      else 
      { 
       Factor100 = Factor100 * i; 
      } 

      //iFactorial = i * iFactorial; 

      if (i % Updates == 0) 
      { 
       Worker.ReportProgress(50, new Tuple<string, BigInteger>("Factorialising", i)); 
       using (StreamWriter DropWriter = File.CreateText(@FileLocation + "FactorialDropCatcher.dat")) 
       { 
        DropWriter.WriteLine("N: " + i); 
        DropWriter.WriteLine("N!: " + iFactorial); 
       } 
      } 
     } 

だから、私はすぐにそれが必要になるまでごとに一度だけ万更新実行中の階乗の数を維持する、めちゃくちゃ大きな数字の計算から滞在してみました:ここには、私が持っているものです。

これをもっと速く計算するにはどうすればよいですか?

+0

これはプログラミングの問題よりもむしろ数学的であり、あなたがしたことを説明していないかもしれません(あらかじめ計算された階乗はおそらく?)。進行状況を表示するのは高価ですが、すでにそれを減らしています。 – Sinatr

+0

'1000000000! = 9.90462 ... 38144'( '8565705522'数字)の後に' 249999998'が続きます。末尾のゼロを削除した場合、(最高で) '8565705522 - 249999998 == 8315705524' - ** 3%**の改善 –

+2

なぜ* exact *階乗値が欲しいのですか? * Stirling formula *は合理的な近似を提供します:https://en.wikipedia.org/wiki/Stirling%27s_approximation –

答えて

0

このため、IEnumerableの拡張メソッド<int>.Product()を使用します。 IEnumerable <int> .Sum()と同じですが、製品です。 Nの階乗については、1からNまでの範囲を作成し、その製品を取ります。

これは驚くほど速く、数字のクランチニーズがかなり極端であれば、PLINQを使用するように変更するのは簡単です!

public class FactorialExample 
{ 
    public static BigInteger Factorial(int n) 
    { 
     return Enumerable.Range(2, n).Product(); 
    }  
} 

public static class IEnumerableExtensionMethods 
{ 
    public static BigInteger Product(this IEnumerable<int> multiplicands) 
    { 
     System.Numerics.BigInteger result = 1; 
     foreach (int multiplier in multiplicands) 
     { 
      result = System.Numerics.BigInteger.Multiply(result, multiplier); 
     } 
     return result; 
    } 
} 
関連する問題