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

时间:2015-10-12 19:34:49

标签: python performance exception recursion compare

首先,我必须为我糟糕的英语道歉,但我会尽我所能。

我在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中的异常是如此之慢?或者问题是什么?建立一堆例外? 谢谢你的回复。

1 个答案:

答案 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倍)