8

多数の被乗数 (小さな式) を持つ乗法式があるとします。

expression = a*b*c*d*....*w   

たとえば、c は (x-1)、d は (y**2-16)、k は (x y-60)..... x、y は数字
で、c、d、k、
jゼロかもしれない
c
d k j....*w と書く方が良いですか、それとも python は私が書いた順序に関係なくすべての式を評価しますか?

4

5 に答える 5

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        

更新: 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        

つまり、式に変数が含まれる場合、順序は関係ありません。すべてが評価されます。

于 2010-07-16T11:54:13.197 に答える
5

ベンチマークする前に最適化しようとしないでください。

それを念頭に置いて、中間項がゼロであっても、すべての式が評価されるのは事実です。

順序はまだ重要かもしれません。式は左から右に評価されます。が非常に大きい場合a,b,c,...、Python に大量のメモリを割り当てさせ、 になる前に計算を遅くする可能性がありますj=0。(j=0式の前に来た場合、積はそれほど大きくならず、追加のメモリ割り当ては必要ありません)。

timeitまたはcProfileでコードのタイミングを計った後、これが自分の状況である可能性があると思われる場合は、事前評価c,d,k,jとテストを試すことができます

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

次に、これをtimeitorcProfileと合わせて時間を計ります。これがあなたの状況で役立つかどうかを実際に判断する唯一の方法は、ベンチマークすることです。

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

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
于 2010-07-16T11:53:49.453 に答える
5

これは、Python 3.1 での簡単なチェックです。

>>> import timeit
>>> timeit.timeit('243*325*(5539**35)*0')
0.5147271156311035
>>> timeit.timeit('0*243*325*(5539**35)')
0.153839111328125

そしてこれはPython 2.6で:

>>> timeit.timeit('243*325*(5539**35)*0')
0.72972488403320312
>>> timeit.timeit('0*243*325*(5539**35)')
0.26213502883911133

したがって、注文はそれに入ります。

また、Python 3.1 で次の結果を得ました。

>>> timeit.timeit('(256**256)*0')
0.048995018005371094
>>> timeit.timeit('0*(256**256)')
0.1501758098602295

なぜ地球上で?

于 2010-07-16T12:14:21.120 に答える
2

>>> import timeit
>>> timeit.timeit('1*2*3*4*5*6*7*8*9*9'*6)
0.13404703140258789
>>> timeit.timeit('1*2*3*4*5*6*7*8*9*0'*6)
0.13294696807861328
>>> 
于 2010-07-16T11:52:37.893 に答える
-1

おそらくそうではありません。乗算は、すべての中で最も安価な操作の1つです。0の方が速い場合は、前にゼロをチェックする必要があります。これは、乗算を行うよりもおそらく遅いでしょう。

最速の解決策はmultiply.reduce()

于 2010-07-16T11:48:37.933 に答える