首先,我必须为我糟糕的英语道歉,但我会尽我所能。
我在python中使用递归和异常来计算阶乘的比较速度。
我写了一段代码:
class MyException(Exception):
def __init__(self, value):
self.value = value
def standardFactorial(n):
if n == 1:
return 1
return n * standardFactorial(n-1)
def factorialWithExceptions(n):
if n == 1:
raise MyException(1)
try:
factorialWithExceptions(n-1)
except MyException as x:
raise MyException(n * x.value)
为因子300运行10 000次,我得到的结果如下:
recursion
1.233912572992267
exceptions
9.093736120994436
有人可以向我解释为什么差异如此之大? python中的异常是如此之慢?或者问题是什么?建立一堆例外? 谢谢你的回复。
答案 0 :(得分:0)
例外情况应该是针对“特殊”条件。 Python的实现应该比Java更轻,这导致pythonic方法倾向于比java更频繁地使用异常(有一个座右铭:更好地请求宽恕而不是允许)。即便如此,在几乎所有语言中都使用流控制的异常,因为它使代码更难以推理,并且因为创建异常,捕获它,解除所有位,并继续
据说,仅仅为了比较,我测试了java等价物(使用BigInteger,因为只是使用整数导致阶乘(300)的无意义结果。第一次,我得到了非常奇怪的结果,我将不得不看看,但更新代码在同一个应用程序中执行这两个操作并进行一些检查,希望确保我们不会因为优化等而得到假结果。
import java.math.BigInteger;
class BigIntegerHolder extends Exception
{
public BigInteger bigInt;
public BigIntegerHolder(BigInteger x) { this.bigInt = x; }
}
class Factorial
{
public static BigInteger fact(int n)
{
if (n == 1)
{
return BigInteger.valueOf(1);
}
return fact(n-1).multiply(BigInteger.valueOf(n));
}
public static void factExcept(int n) throws BigIntegerHolder
{
if (n == 1)
{
throw new BigIntegerHolder(BigInteger.valueOf(1));
}
try {
factExcept(n-1);
}
catch (BigIntegerHolder ex)
{
throw new BigIntegerHolder( ex.bigInt.multiply(BigInteger.valueOf(n)));
}
}
public static void main(String args[])
{
BigInteger realValue = fact(300);
int count = 0;
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
{
try {
factExcept(300);
}
catch (BigIntegerHolder ex)
{
if (realValue.equals(ex.bigInt))
{
count += 1;
}
}
}
long end = System.currentTimeMillis();
System.out.println("We got it right " + count + " times in " + (end - start) + " ms");
count = 0;
start = System.currentTimeMillis();
for (int j = 0; j < 10000; j++)
{
BigInteger x = fact(300);
if (realValue.equals(x))
{
count += 1;
}
}
end = System.currentTimeMillis();
System.out.println("We got it right " + count + " times in " + (end - start) + " ms");
}
}
输出:
我们在23708毫秒内完成了10000次
我们在271毫秒内完成了10000次
(表明在Java中,使用异常这样做几乎要慢100倍)