【发布时间】:2013-07-09 05:00:21
【问题描述】:
我遇到的一个编程问题涉及计算大数(最多 10^5 的数)的阶乘。我见过一个简单的 Haskell 代码,它是这样的
factorial :: (Eq x, Num x) => x -> x
factorial 0 = 1
factorial a = a * factorial (a - 1)
它隐式地处理大量数字,并且即使在代码中不涉及任何缓存的情况下也能以某种方式运行得更快。
当我尝试使用 Java 解决问题时,我不得不使用 BigInteger 来保存巨大的数字并使用迭代版本的阶乘
public static BigInteger factorialIterative(int n)
{
if(n == 0 || n == 1) return BigInteger.valueOf(1);
BigInteger f = BigInteger.valueOf(1);
for(int i = 1 ; i <= n ;i++)
f = f.multiply(BigInteger.valueOf(i));
return f;
}
以上代码超出了程序设定的执行时间限制。我还尝试了阶乘的缓存递归版本
public static BigInteger factorial(int n)
{
if(cache[n] != null)
return cache[n];
else if(n == 0)
return new BigInteger("1");
else {
cache[n] = n* factorial(n - 1);
return cache[n];
}
}
这给了我一个内存不足的错误(可能是由于递归)。
我的问题是,为什么像 Haskell 这样的函数式编程语言在处理这类涉及大量数字的问题时更好? (尽管没有明显的缓存)。有没有办法让 java 代码运行得和 Haskell 代码一样快?
【问题讨论】:
-
如果您提供完整的(可运行的)程序并准确说明您是如何编译和运行它们的,那就太好了。问题可能不是您所期望的。
-
我正在将代码上传到一个编程挑战网站link,该网站为包括 Java 和 Haskell 在内的各种语言提供编译器。虽然我不知道他们使用哪种编译器
-
好的,我自己对它进行了基准测试,我还发现 Java 代码比 Haskell 代码慢得多。我的猜测是这是一个问题,因为 Java 的
BigInteger比 GMP 慢得多(GHC 用于Integer的库),并且几乎与语言本身无关。