找到阶乘的有效方法

时间:2013-08-21 11:57:01

标签: c++ data-structures

除了正常的递归函数和循环方法之外,找到一个数的阶乘的有效方法是什么?由于普通方法产生输出的时间太长,有没有办法比递归和循环方法减少时间复杂度?如果不是为什么?

6 个答案:

答案 0 :(得分:7)

79年以来!是1.711E98你只需要一个79个数字的列表来使用查找表。 因子列在:http://www.tsm-resources.com/alists/fact.html以整数格式列出或以http://home.ccil.org/~remlaps/javascript/jstest1.html以科学格式列出,因此它只是“剪切和粘贴”

答案 1 :(得分:2)

如果您想计算许多阶乘值,那么在您继续进行缓存值是一种选择。

如果您只计算一次factorial(n),那么循环可能是您获得的最佳效果。你可以通过一些循环展开来获得更多的处理器(一次计算两次或四次乘法),但它不太适用于非常大的因子,因为乘法本身就变成了一系列冗长的指令。

据我所知,没有“神奇”的数学来计算12 * 13 * 14 * 15或类似的序列,而不是将它们相乘。

答案 2 :(得分:2)

您可以使用Stirling's approximation来评估大型因子。

答案 3 :(得分:2)

由于你的一条评论说你想要找到100000!,这个答案涵盖了很大的因素。

如果您不需要确切答案,可以使用Stirling's Approximation

如果你想要一个确切的答案,你需要使用像GMP这样的任意精度数学包 arbitrary precision math package

答案 4 :(得分:0)

不,不是真的。如果您担心运行时成本,可以使用查找表(需要使用预先计算的值)来减少运行时成本。

存储每个因子可能需要太多的内存,所以让我们存储每个k:thialial。 这将要求程序在运行时执行多达k次乘法。

假设您的运行时性能要求限制为每个阶乘1000次乘法。然后你需要预先计算和存储1000!,2000!,3000!等等,直到您想要支持的上限(可用内存将限制您)。

由于阶乘很快会变得比原生数据类型大,所以你需要一个可以处理大数的类。我假设它存在这样一个类,它被称为BigInteger

BigInteger preCalculatedValues[] = { new BigInteger("1"), new BigInteger("<value of 1000!>"), and so on... }

BigInteger factorial(int n) {
  int pre = n/1000;
  int i;
  if (pre > LARGEST_VALUE_HANDLED) { 
    // Either throw an exception or let it take longer. I choose to let it take longer.
    pre = LARGEST_VALUE_HANDLED;
  }
  BigInteger result = preCalculatedValues[pre];
  for (i = pre * 1000 + 1; i <= n; i++) {
     result.multiplyWith(i);  // This operation is probably overloaded on the * operator
  }
}

答案 5 :(得分:0)

计算非常大的事实的最简单方法是使用 伽玛函数。另一方面:它不会那么快 表查找(由其他人提出);如果你正在使用内置 在类型中,您需要以下表格:

for 32 bits: 12 entries
for 64 bits: 20 entries
for float:   34 entries
for double: 170 entries

(上表中可能有一个错误。我写道 用于快速计算它们的代码。)

对于double,可能对于float,通常的循环方法 无论如何,可能会引入太多的舍入错误。如果你 不想使用表,你有C ++ 11, exp( lgamma( i + 1 ) )应该做到这一点。 (如果你不这样做 拥有C ++ 11,无论如何你可能拥有lgamma函数。它的 在C99。)

如果你正在处理某种扩展范围类型,那么你 可能必须为您的类型实施lgamma(和exp)。