为什么Python中floatingpoint除法用更小的数字更快?

2024-06-28 19:31:28 发布

您现在位置:Python中文网/ 问答频道 /正文

在回答this question的过程中,我遇到了一些我无法解释的事情。在

给出以下python3.5代码:

import time

def di(n):
    for i in range(10000000): n / 101

i = 10
while i < 1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000:
    start = time.clock()
    di(i)
    end = time.clock()
    print("On " + str(i) + " " + str(end-start))
    i *= 10000

输出为:

^{pr2}$

如您所见,大约有两次:一次是针对较小的数字,另一次是针对较大的数字。在

Python2.7也会出现同样的结果,使用以下函数来保留语义:

def di(n):
    for i in xrange(10000000): n / 101.0

在同一台机器上,我得到:

On 10 0.617427
On 100000 0.61805
On 1000000000 0.6366
On 10000000000000 0.620919
On 100000000000000000 0.616695
On 1000000000000000000000 0.927353
On 10000000000000000000000000 1.007156
On 100000000000000000000000000000 0.98597
On 1000000000000000000000000000000000 0.99258
On 10000000000000000000000000000000000000 0.966753
On 100000000000000000000000000000000000000000 0.992684
On 1000000000000000000000000000000000000000000000 0.991711
On 10000000000000000000000000000000000000000000000000 0.994703
On 100000000000000000000000000000000000000000000000000000 0.978877
On 1000000000000000000000000000000000000000000000000000000000 0.982035
On 10000000000000000000000000000000000000000000000000000000000000 0.973266
On 100000000000000000000000000000000000000000000000000000000000000000 0.977911
On 1000000000000000000000000000000000000000000000000000000000000000000000 0.996857
On 10000000000000000000000000000000000000000000000000000000000000000000000000 0.972555
On 100000000000000000000000000000000000000000000000000000000000000000000000000000 0.985676
On 1000000000000000000000000000000000000000000000000000000000000000000000000000000000 0.987412
On 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0.997207
On 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0.970129

为什么较小的数字和较大的数字的浮点除法之间会有这种一致的差异?这是否与Python内部对较小的数字使用float而对较大的数字使用double有关?在


Tags: infortimeon过程def数字this
2条回答

它与Python将精确的整数存储为bignum有关。在

在Python2.7中,计算integera/floatfb,首先将整数转换为float。如果将整数存储为Bignum[注1],则需要更长的时间。所以除法不是有差分代价的,而是整数(可能是Bignum)到double的转换。在

python3对integera/floatfb执行相同的计算,但是对于integera,python3尝试计算最接近的可表示结果,这可能与原始的float(a) / float(b)略有不同。(这类似于经典的双舍入问题。)

如果float(a)和{}都是精确的(也就是说,a和{}都不大于53位),则朴素的解决方案有效,并且结果只需要对两个双精度浮点进行除法。在

否则,执行多精度除法以生成正确的53位尾数(指数单独计算),并将结果精确转换为浮点数。这种划分有两种可能:如果b足够小,足以容纳单个Bignum单元(这适用于OP中的基准测试),那么快速跟踪;当{}较大时,则使用较慢的通用Bignum除法。在

在上述任何情况下,观察到的速度差与硬件执行浮点除法的速度无关。对于最初的python3.5测试,区别在于执行的是浮点还是Bignum除法;对于python2.7,区别在于必须将Bignum转换为double。在

感谢@MarkDickinson的澄清,以及实现算法的the source code (with a long and useful comment)的指针。在


注释

  1. 在python3中,整数总是存储为bignum。Python2对int(64位整数)和long(bignum)有不同的类型。在实践中,由于python3经常在Bignum只有一个“leg”时使用优化算法,“small”和“big”整数之间的差别仍然很明显。在

正如@rici所说,它是更大的整数格式。我把最初的10改为10.0。。。结果是,时间没有明显变化。在

On 10.0 1.12
On 100000.0 0.79
On 1000000000.0 0.79
On 1e+13 0.77
On 1e+17 0.78
On 1e+21 0.79
On 1e+25 0.77
On 1e+29 0.8
On 1e+33 0.77
On 1e+37 0.8
On 1e+41 0.78
On 1e+45 0.78
On 1e+49 0.78
On 1e+53 0.79
On 1e+57 0.77
On 1e+61 0.8
On 1e+65 0.77
On 1e+69 0.79
On 1e+73 0.77
On 1e+77 0.78
On 1e+81 0.78
On 1e+85 0.78
On 1e+89 0.77

相关问题 更多 >