Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 2:为什么楼层除法运算符比普通除法运算符快?_Python_Python 2.7 - Fatal编程技术网

Python 2:为什么楼层除法运算符比普通除法运算符快?

Python 2:为什么楼层除法运算符比普通除法运算符快?,python,python-2.7,Python,Python 2.7,考虑下面的Python2代码 from timeit import default_timer def floor(): for _ in xrange(10**7): 1 * 12 // 39 * 2 // 39 * 23 - 234 def normal(): for _ in xrange(10**7): 1 * 12 / 39 * 2 / 39 * 23 - 234 t1 = default_timer() floor() t2 =

考虑下面的Python2代码

from timeit import default_timer

def floor():
    for _ in xrange(10**7):
        1 * 12 // 39 * 2 // 39 * 23 - 234

def normal():
    for _ in xrange(10**7):
        1 * 12 / 39 * 2 / 39 * 23 - 234

t1 = default_timer()
floor()
t2 = default_timer()
normal()
t3 = default_timer()

print 'Floor  %.3f' % (t2 - t1)
print 'Normal %.3f' % (t3 - t2)
我电脑上的输出是

Floor  0.254
Normal 1.766

那么,为什么楼层除法运算符
/
比普通除法运算符
/
做同一件事时要快?

您可以使用以下命令检查特定python函数的编译字节码:


Python解释器在
floor
中预先计算循环内的表达式,但在
normal
中没有

下面是楼层的代码:

>>> dis.dis(floor)

  5           0 SETUP_LOOP              24 (to 27)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_CONST               9 (10000000)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                10 (to 26)
             16 STORE_FAST               0 (_)

  6          19 LOAD_CONST              15 (-234)
             22 POP_TOP             
             23 JUMP_ABSOLUTE           13
        >>   26 POP_BLOCK           
        >>   27 LOAD_CONST               0 (None)
             30 RETURN_VALUE        
您可以看到表达式已计算
LOAD\u CONST 15(-234)

对于
normal
,这是相同的:

>>> dis.dis(normal)

  9           0 SETUP_LOOP              44 (to 47)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_CONST               9 (10000000)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                30 (to 46)
             16 STORE_FAST               0 (_)

 10          19 LOAD_CONST              10 (12)
             22 LOAD_CONST               5 (39)
             25 BINARY_DIVIDE       
             26 LOAD_CONST               6 (2)
             29 BINARY_MULTIPLY     
             30 LOAD_CONST               5 (39)
             33 BINARY_DIVIDE       
             34 LOAD_CONST               7 (23)
             37 BINARY_MULTIPLY     
             38 LOAD_CONST               8 (234)
             41 BINARY_SUBTRACT     
             42 POP_TOP             
             43 JUMP_ABSOLUTE           13
        >>   46 POP_BLOCK           
        >>   47 LOAD_CONST               0 (None)
             50 RETURN_VALUE        
这一次,计算只是部分简化(例如:省略了初始的
1*
),并且大多数操作都是在运行时执行的

看起来Python2.7没有执行包含不明确的
/
运算符的常量折叠(这可能是整数或浮点除法,具体取决于其操作数)。在程序顶部添加来自uuu future uuuu import division的
,会导致常量在
normal
中折叠,就像在
floor
中一样(尽管结果当然不同,因为现在的
//code>是浮点除法)

这并不是说解释器不能用默认的
/
操作符进行常量折叠,但是它不能。也许代码是从Python3中移植回来的,并且认为使用不明确的除法运算符并不重要。

“产生相同的结果”并不意味着“以相同的方式实现”。 还要注意的是,这些运算符并不总是产生与此处所述相同的结果:

因此,性能度量在很大程度上取决于实现。 通常,硬件浮点除法比整数除法耗时更长。
可能是python经典除法(您称之为普通除法)是通过硬件浮点除法实现的,只有在最后阶段才被截断回整数,而真正的除法(您称之为floored)是通过硬件int除法实现的,这要快得多。

Yes,但是为什么会这样呢?@avamsi我进一步调查了一下,并补充了一些细节。
>>> dis.dis(normal)

  9           0 SETUP_LOOP              44 (to 47)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_CONST               9 (10000000)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                30 (to 46)
             16 STORE_FAST               0 (_)

 10          19 LOAD_CONST              10 (12)
             22 LOAD_CONST               5 (39)
             25 BINARY_DIVIDE       
             26 LOAD_CONST               6 (2)
             29 BINARY_MULTIPLY     
             30 LOAD_CONST               5 (39)
             33 BINARY_DIVIDE       
             34 LOAD_CONST               7 (23)
             37 BINARY_MULTIPLY     
             38 LOAD_CONST               8 (234)
             41 BINARY_SUBTRACT     
             42 POP_TOP             
             43 JUMP_ABSOLUTE           13
        >>   46 POP_BLOCK           
        >>   47 LOAD_CONST               0 (None)
             50 RETURN_VALUE        
normal
 10           0 SETUP_LOOP              24 (to 27)
              3 LOAD_GLOBAL              0 (xrange)
              6 LOAD_CONST               9 (10000000)
              9 CALL_FUNCTION            1
             12 GET_ITER            
        >>   13 FOR_ITER                10 (to 26)
             16 STORE_FAST               0 (_)

 11          19 LOAD_CONST              15 (-233.6370808678501)
             22 POP_TOP             
             23 JUMP_ABSOLUTE           13
        >>   26 POP_BLOCK           
        >>   27 LOAD_CONST               0 (None)
             30 RETURN_VALUE