为何Python 3.1在此代码上比2.6慢?

5 投票
2 回答
743 浏览
提问于 2025-04-16 01:07

考虑以下代码(来自这里,测试次数有所增加):

from timeit import Timer

def find_invpow(x,n):
    """Finds the integer component of the n'th root of x,
    an integer such that y ** n <= x < (y + 1) ** n.
    """
    high = 1
    while high ** n < x:
        high *= 2
    low = high/2
    while low < high:
        mid = (low + high) // 2
        if low < mid and mid**n < x:
            low = mid
        elif high > mid and mid**n > x:
            high = mid
        else:
            return mid
    return mid + 1

def find_invpowAlt(x,n):
    """Finds the integer component of the n'th root of x,
    an integer such that y ** n <= x < (y + 1) ** n.
    """
    low = 10 ** (len(str(x)) / n)
    high = low * 10
    while low < high:
        mid = (low + high) // 2
        if low < mid and mid**n < x:
            low = mid
        elif high > mid and mid**n > x:
            high = mid
        else:
            return mid
    return mid + 1

x = 237734537465873465
n = 5
tests = 1000000

print "Norm", Timer('find_invpow(x,n)', 'from __main__ import find_invpow, x,n').timeit(number=tests)
print "Alt", Timer('find_invpowAlt(x,n)', 'from __main__ import find_invpowAlt, x,n').timeit(number=tests)

在使用Python 2.6时(Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41) [GCC 4.4.3] on linux2),报告的运行时间是:

Norm 9.73663210869
Alt 9.53973197937

但是,在同一台机器上使用Python 3.1时(Python 3.1.2 (r312:79147, Apr 15 2010, 15:35:48) [GCC 4.4.3] on linux2),运行时间是:

Norm 28.4206559658
Alt 26.8007400036

有没有人知道为什么这段代码在Python 3.1上运行速度慢了三倍?

2 个回答

2

//这个符号在Python 2和Python 3中都用来进行整数除法(也叫向下取整除法),而/这个符号在Python 2中对整数进行除法时也是向下取整,但在Python 3中无论是什么数字都进行真实除法。

试着把/换成//吧。

3

我在使用2.5、2.6、2.7和3.1版本(Windows XP SP2)时,发现运行时间逐渐减少。在使用“/”这个版本时,3.1的运行时间明显比2.X的要小得多,比如说“Norm”从6.35(py2.7)降到了3.62(py3.1)。

需要注意的是,在2.x版本中,有两种数字类型:ints(机器字长,32位或64位)和longs(可变长度)。而在3.x版本中,long被重新命名为int,原来的int类型消失了。我猜测,从long转换为float可能会导致使用“/”时的额外时间。

无论如何,一个更好的“替代”版本可以从这段代码开始:

high = 1
highpown = 1
while highpown < x:
    high <<= 1
    highpown <<= n

撰写回答