【问题标题】:Calculating large factorials accurately准确计算大阶乘
【发布时间】:2016-11-29 20:39:07
【问题描述】:

我需要计算一个非常大的阶乘,但它必须是精确的。我不能使用近似值。

我想获得 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);
                }
            }
        }

因此,在必要之前,我尽量避免计算这些异常大的数字,保持运行中的阶乘数字每 10,000 次才更新一次。

我怎样才能更快地计算出来?

【问题讨论】:

  • 这是一个数学问题,而不是编程问题,而且你没有解释你做了什么(可能是预先计算的阶乘?)。显示进度很昂贵,您已经减少了它。
  • 1000000000! = 9.90462...381448565705522 数字)只有 249999998 尾随零。如果您删除尾随零,您将(最多)8565705522 - 249999998 == 8315705524 - 3% 改进
  • 为什么要exact阶乘值? 斯特林公式提供了一个合理的近似值:en.wikipedia.org/wiki/Stirling%27s_approximation
  • @Sinatr 我只是有一种方法可以为它提供我上次保存的值,所以我可以给它一个 i 和 iFactorial 的值,该值之前保存到文本文件中。否则,此时它们都等于 1。 DmitryBychenko 我需要它是确切的数字,如 OP 中所述。原因是我计划执行的计算取决于它的确切数字。
  • 什么样的计算?也许解释问题here 将帮助您获得优化的公式,这不需要执行那么多迭代。你似乎高估了准确性。

标签: c# biginteger factorial


【解决方案1】:

为此,我只使用 IEnumerable.Product() 的扩展方法。它就像 IEnumerable.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;
    }
}

【讨论】:

    猜你喜欢
    • 2014-11-22
    • 2022-01-17
    • 1970-01-01
    • 2023-03-22
    • 2010-11-25
    • 2015-04-19
    • 1970-01-01
    • 2013-02-19
    相关资源
    最近更新 更多