为什么对于非常大的数字,除法会变得更快

Why does division become faster with very large numbers

我想看看除法运算的常数,所以我运行这段代码

import time

def di(n):
    n/101

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

这就是我得到的输出

On 10 5.98714047756e-06
On 100000 4.7041818038e-06
On 1000000000 2.56591734753e-06
On 10000000000000 2.99357023878e-06
On 100000000000000000 2.99357023878e-06
On 1000000000000000000000 2.99357023879e-06
On 10000000000000000000000000 2.99357023878e-06
On 100000000000000000000000000000 3.42122313003e-06
On 1000000000000000000000000000000000 3.42122313003e-06
On 10000000000000000000000000000000000000 3.84887602128e-06
On 100000000000000000000000000000000000000000 3.42122313003e-06
On 1000000000000000000000000000000000000000000000 3.84887602128e-06
On 10000000000000000000000000000000000000000000000000 1.71061156501e-06
On 100000000000000000000000000000000000000000000000000000 1.71061156502e-06
On 1000000000000000000000000000000000000000000000000000000000 1.71061156501e-06
On 10000000000000000000000000000000000000000000000000000000000000 2.13826445628e-06
On 100000000000000000000000000000000000000000000000000000000000000000 1.71061156502e-06
On 1000000000000000000000000000000000000000000000000000000000000000000000 2.13826445628e-06
On 10000000000000000000000000000000000000000000000000000000000000000000000000 2.13826445628e-06
On 100000000000000000000000000000000000000000000000000000000000000000000000000000 2.13826445626e-06
On 1000000000000000000000000000000000000000000000000000000000000000000000000000000000 2.13826445626e-06

为什么除法通常在后面变得更快,而不是前两项最小的时间?

Why does the division generally get faster later on as opposed to the time of the first two terms which are the smallest?

实际上并没有。如果我将 di 替换为:

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

然后我得到(Python 3.5,我猜你正在使用):

On 10 0.546889
On 100000 0.545004
On 1000000000 0.5454929999999998
On 10000000000000 0.5519709999999998
On 100000000000000000 1.330797
On 1000000000000000000000 1.31053
On 10000000000000000000000000 1.3393129999999998
On 100000000000000000000000000000 1.3524339999999997
On 1000000000000000000000000000000000 1.3817269999999997
On 10000000000000000000000000000000000000 1.3412670000000002
On 100000000000000000000000000000000000000000 1.3358929999999987
On 1000000000000000000000000000000000000000000000 1.3773859999999996
On 10000000000000000000000000000000000000000000000000 1.3326890000000002
On 100000000000000000000000000000000000000000000000000000 1.3704769999999993
On 1000000000000000000000000000000000000000000000000000000000 1.3235019999999995
On 10000000000000000000000000000000000000000000000000000000000000 1.357647
On 100000000000000000000000000000000000000000000000000000000000000000 1.3341190000000012
On 1000000000000000000000000000000000000000000000000000000000000000000000 1.326544000000002
On 10000000000000000000000000000000000000000000000000000000000000000000000000 1.3671139999999973
On 100000000000000000000000000000000000000000000000000000000000000000000000000000 1.3630120000000012
On 1000000000000000000000000000000000000000000000000000000000000000000000000000000000 1.3600200000000022
On 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1.3189189999999975
On 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1.3503469999999993

大家可以看到,大致有两种,一种是小数,一种是大数。在 Python 3.5 中,/ 进行浮点除法,因此无论数字的大小如何,它实际上应该花费大约相同的时间。

不过,还是有从小到大的差距。 Python 2.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

这与将整数转换为浮点数有关(具体细节待定)。对于超过某个点的整数,这会更慢,并且当超过该点时,除法开始花费更长的时间。

"Division generally gets faster" 并未准确描述您的观察结果。看起来他们变得更快,然后更慢,然后更快,然后更慢,然后更快,然后更慢,然后更快。我尝试对您的脚本进行两​​次修改:

  1. 在 while 循环中,不是只调用 di 一次,而是调用它 10 次并打印出最小、最大和平均时间。我发现最大时间大致显示了您所看到的模式,并且最小时间为 0.0,因此解释器可能正在缓存函数调用的结果作为优化。
  2. 颠倒了输入的顺序,所以从 i 的大数字开始,每次都下降 i /= 10000。最大时间在这里显示出类似的模式,因为前几次计算比其余计算花费更多的时间。也就是说,无论是从小数开始的程序还是从大数开始的程序,无论先做什么计算似乎都需要更多时间。