比较递归和异常的速度- Python



首先我必须为我的英语说抱歉,但我正在努力。

我有一个练习,比较在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的阶乘运行10000次,得到如下结果:

recursion
1.233912572992267
exceptions
9.093736120994436

谁能给我解释一下为什么差异这么大?python中的异常这么慢?或者问题是什么?构建异常堆栈?谢谢你的回复。

异常应该用于"异常"条件。Python的实现应该比Java的稍微轻一点,这导致Python的方法倾向于比Java更频繁地使用异常(有一句格言:请求原谅比请求许可更好)。即便如此,使用异常进行流控制在几乎所有语言中都是不受欢迎的,因为它使得对代码进行推理变得更加困难,而且因为创建异常、捕获异常、展开所有位并继续执行会对性能造成影响。

说了这么多,为了比较,我测试了java的等效物(使用BigInteger的,因为只使用int会导致factorial(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倍)

最新更新