2016-07-26 9 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'가 후행합니다. 후행 0을 제거하면 기껏해야 '8565705522 - 249999998 == 8315705524' - ** 3 % ** 향상 –

+2

왜 * 정확한 * 계승 값을 원하십니까? * 스털링 공식 *은 합리적인 근사값을 제공합니다. https://en.wikipedia.org/wiki/Stirling%27s_approximation –

답변

0

이 경우 IEnumerable < >.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; 
    } 
}