比较递归和异常的速度

2024-09-30 18:27:11 发布

您现在位置: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中的异常如此缓慢?或者有什么问题?构建异常堆栈? 谢谢你的回复。你知道吗


Tags: 代码selfreturnifinitvaluedefexception
1条回答
网友
1楼 · 发布于 2024-09-30 18:27:11

例外情况应该是“例外”情况。Python的实现应该比Java稍微轻一些,这导致pythonic方法倾向于比Java方法更频繁地使用异常(有一条格言:请求原谅比允许更好)。即便如此,在几乎所有的语言中,使用异常进行流控制都是不受欢迎的,因为这使得对代码进行推理变得更加困难,同时也因为创建异常、捕获异常、释放所有位并继续进行操作会对性能造成影响。你知道吗

也就是说,为了进行比较,我测试了java等价物(使用BigInteger,因为仅仅使用int会导致阶乘(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");

    }
}

这将输出:

We got it right 10000 times in 23708 ms

We got it right 10000 times in 271 ms

(这表明在Java中,使用异常进行操作的速度几乎慢了100倍)

相关问题 更多 >