您将如何编写非递归算法来计算阶乘?
您将如何编写非递归算法来计算 n!
?
How would you write a non-recursive algorithm to compute n!
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
您将如何编写非递归算法来计算 n!
?
How would you write a non-recursive algorithm to compute n!
?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(22)
因为 Int32 在任何大于 12 的数据上都会溢出! 不管怎样,只要这样做:
Since an Int32 is going to overflow on anything bigger than 12! anyway, just do:
在伪代码中
in pseudocode
为了科学的利益,我对计算阶乘的算法的各种实现进行了一些分析。 我用 C# 和 C++ 创建了每种方法的迭代、查找表和递归实现。 我将最大输入值限制为 12 或更少,因为是 13! 大于 2^32(32 位 int 所能容纳的最大值)。 然后,我运行每个函数 1000 万次,循环遍历可能的输入值(即将 i 从 0 增加到 1000 万次,使用 i 模 13 作为输入参数)。
以下是标准化为迭代 C++ 数字的不同实现的相对运行时间:
并且,为了完整起见,以下是使用 64 位整数并允许输入值最多 20 的实现的相对运行时间:
In the interests of science I ran some profiling on various implementations of algorithms to compute factorials. I created iterative, look up table, and recursive implementations of each in C# and C++. I limited the maximum input value to 12 or less, since 13! is greater than 2^32 (the maximum value capable of being held in a 32-bit int). Then, I ran each function 10 million times, cycling through the possible input values (i.e. incrementing i from 0 to 10 million, using i modulo 13 as the input parameter).
Here are the relative run-times for different implementations normalized to the iterative C++ figures:
And, for completeness, here are the relative run-times for implementations using 64-bit integers and allowing input values up to 20:
将递归解决方案重写为循环。
Rewrite the recursive solution as a loop.
除非像 Python 中那样有任意长度的整数,否则我会将 Factorial() 的预先计算值存储在大约 20 个长整型的数组中,并使用参数 n 作为索引。 n! 的增长率 比较高,计算20! 或21! 无论如何,即使在 64 位机器上,你也会遇到溢出。
Unless you have arbitrary-length integers like in Python, I would store the precomputed values of factorial() in an array of about 20 longs, and use the argument n as the index. The rate of growth of n! is rather high, and computing 20! or 21! you'll get an overflow anyway, even on 64-bit machines.
这是预先计算的函数,但实际上是正确的。 正如前面所说,13! 溢出,因此计算这么小的值范围是没有意义的。 64 位更大,但我希望这个范围仍然相当合理。
资料来源:http://ctips.pbwiki.com/Factorial
Here's the precomputed function, except actually correct. As been said, 13! overflows, so there is no point in calculating such a small range of values. 64 bit is larger, but I would expect the range to still be rather reasonable.
Source: http://ctips.pbwiki.com/Factorial
我喜欢 pythonic 解决方案:
I love the pythonic solution to this:
在运行时这是非递归的。 在编译时它是递归的。 运行时性能应为 O(1)。
At run time this is non-recursive. At compile time it is recursive. Run-time performance should be O(1).
对于非递归方法,没有比这更简单的了
For a non-recursive approach, it can't get simpler than this
伪代码
Pseudo code
假设您希望能够处理一些非常大的数字,我将按如下方式编码。 如果您希望在常见情况下(低数字)有足够的速度,但希望能够处理一些超繁重的计算,则可以使用此实现。 我认为这是理论上最完整的答案。 在实践中,我怀疑除了家庭作业问题之外,您是否需要计算如此大的阶乘
assuming you wanted to be able to deal with some really huge numbers, I would code it as follows. This implementation would be for if you wanted a decent amount of speed for common cases (low numbers), but wanted to be able to handle some super hefty calculations. I would consider this the most complete answer in theory. In practice I doubt you would need to compute such large factorials for anything other than a homework problem
我会使用记忆法。 这样,您可以将该方法编写为递归调用,并且仍然可以获得线性实现的大部分好处。
I would use memoization. That way you can write the method as a recursive call, and still get most of the benefits of a linear implementation.
迭代:
或者...在 Haskell 中使用尾递归:
在这种情况下尾递归的作用是使用累加器来避免堆栈调用上的堆积。
参考:Haskell 中的尾递归
Iterative:
Or... using tail recursion in Haskell:
What tail recursion does in this case is uses an accumulator to avoid piling on stack calls.
Reference: Tail Recursion in Haskell
Java 中的非递归阶乘。 该解决方案使用自定义迭代器(以演示迭代器的使用:))。
Non recursive factorial in Java. This solution is with custom iterator (to demonstrate iterator use :) ).
递归地使用带有缓存的 JavaScript。
Recursively using JavaScript with caching.