如果找到零,python乘法表达式的计算速度会更快吗?

Lor*_*ish 8 python math optimization evaluation

假设我有一个乘法表达式,有许多被乘数(小表达式)

expression = a*b*c*d*....*w   
Run Code Online (Sandbox Code Playgroud)

其中例如c是(x-1),d是(y**2-16),k是(x y-60)..... x,y是数字
,我知道c,d,k, j也许为零
我写这个表达式的顺序对于更快的评估很重要吗?
写c
d k j 更好 ....*w或python会评估所有表达式,无论我写的顺序如何?

Nic*_*kis 7

Python v2.6.5不检查零值.

def foo():
    a = 1
    b = 2
    c = 0
    return a * b * c

>>> import dis
>>> dis.dis(foo)
  2           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

  3           6 LOAD_CONST               2 (2)
              9 STORE_FAST               1 (b)

  4          12 LOAD_CONST               3 (3)
             15 STORE_FAST               2 (c)

  5          18 LOAD_FAST                0 (a)
             21 LOAD_FAST                1 (b)
             24 BINARY_MULTIPLY     
             25 LOAD_FAST                2 (c)
             28 BINARY_MULTIPLY     
             29 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

更新:我测试了Baldur的表达式,Python可以并且将优化涉及常量表达式的代码.该奇怪的是,test6没有优化.

def test1():
    return 0 * 1

def test2():
    a = 1
    return 0 * a * 1

def test3():
    return 243*(5539**35)*0

def test4():
    return 0*243*(5539**35)

def test5():
    return (256**256)*0

def test6():
    return 0*(256**256)

>>> dis.dis(test1) # 0 * 1
  2           0 LOAD_CONST               3 (0)
              3 RETURN_VALUE       

>>> dis.dis(test2) # 0 * a * 1
  5           0 LOAD_CONST               1 (1)
              3 STORE_FAST               0 (a)

  6           6 LOAD_CONST               2 (0)
              9 LOAD_FAST                0 (a)
             12 BINARY_MULTIPLY     
             13 LOAD_CONST               1 (1)
             16 BINARY_MULTIPLY     
             17 RETURN_VALUE        

>>> dis.dis(test3) # 243*(5539**35)*0
  9           0 LOAD_CONST               1 (243)
              3 LOAD_CONST               5 (104736434394484...681759461305771899L)
              6 BINARY_MULTIPLY     
              7 LOAD_CONST               4 (0)
             10 BINARY_MULTIPLY     
             11 RETURN_VALUE        

>>> dis.dis(test4) # 0*243*(5539**35)
 12           0 LOAD_CONST               5 (0)
              3 LOAD_CONST               6 (104736433252667...001759461305771899L)
              6 BINARY_MULTIPLY     
              7 RETURN_VALUE        

>>> dis.dis(test5) # (256**256)*0
 15           0 LOAD_CONST               4 (0L)
              3 RETURN_VALUE        

>>> dis.dis(test6) # 0*(256**256)
 18           0 LOAD_CONST               1 (0)
              3 LOAD_CONST               3 (323170060713110...853611059596230656L)
              6 BINARY_MULTIPLY     
              7 RETURN_VALUE        
Run Code Online (Sandbox Code Playgroud)

简而言之,如果表达式包含变量,则顺序无关紧要.一切都将被评估.


unu*_*tbu 5

在基准测试之前不要尝试优化.

考虑到这一点,即使中间项为零,也会评估所有表达式.

订单可能仍然重要.表达式从左到右进行评估.如果a,b,c,...数字非常大,它们可能会迫使Python分配大量内存,从而减慢计算速度j=0.(如果j=0在表达式中较早出现,那么产品将永远不会变得那么大,并且不需要额外的内存分配).

如果在使用timeitcProfile计算代码后,您觉得这可能是您的情况,那么您可以尝试预先评估c,d,k,j和测试

if not all (c,d,k,j):
    expression = 0
else:
    expression = a*b*c*d*....*w
Run Code Online (Sandbox Code Playgroud)

然后用timeit或同时计时cProfile.真正判断这在你的情况下是否有用的唯一方法是进行基准测试.

In [333]: import timeit

In [334]: timeit.timeit('10**100*10**100*0')
Out[334]: 1.2021231651306152

In [335]: timeit.timeit('0*10**100*10**100')
Out[335]: 0.13552498817443848
Run Code Online (Sandbox Code Playgroud)

尽管PyPy要快得多,但它似乎也没有优化它:

% pypy-c
Python 2.7.3 (d994777be5ab, Oct 12 2013, 14:13:59)
[PyPy 2.2.0-alpha0 with GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``http://twitpic.com/52ae8f''
>>>> import timeit
>>>> timeit.timeit('10**100*10**100*0')
0.020643949508666992
>>>> timeit.timeit('0*10**100*10**100')
0.003732919692993164
Run Code Online (Sandbox Code Playgroud)


Ice*_*ack 5

这只是在 Python 3.1 中的快速检查:

>>> import timeit
>>> timeit.timeit('243*325*(5539**35)*0')
0.5147271156311035
>>> timeit.timeit('0*243*325*(5539**35)')
0.153839111328125
Run Code Online (Sandbox Code Playgroud)

这在 Python 2.6 中:

>>> timeit.timeit('243*325*(5539**35)*0')
0.72972488403320312
>>> timeit.timeit('0*243*325*(5539**35)')
0.26213502883911133
Run Code Online (Sandbox Code Playgroud)

所以订单确实进入了它。

我也在 Python 3.1 中得到了这个结果:

>>> timeit.timeit('(256**256)*0')
0.048995018005371094
>>> timeit.timeit('0*(256**256)')
0.1501758098602295
Run Code Online (Sandbox Code Playgroud)

为什么在地球上?

  • 最后的计时结果是由于 CPython 的窥视孔优化器的能力有限。表达式 `(256**256)*0` 的字节码一直向下折叠为单个常量 `0`,因此您的计时根本不包括任何算术运算。对于第二个表达式,`256**256` 被折叠为一个常数,但你仍然需要乘以 `0`。我猜这是因为窥视器基本上是从左到右工作的。 (4认同)
  • 尝试使用变量而不是常量计时 (2认同)