2

私の前の質問の続きとして、PackedArray のリスト積を見つける Simon の方法は高速ですが、負の値では機能しません。

これは最小限の時間ペナルティで「修正」できますAbsが、記号が失われているため、製品の記号を個別に見つける必要があります。

私が試した最速の方法はEvenQ @ Total @ UnitStep[-lst]

lst = RandomReal[{-2, 2}, 5000000];

Do[
  EvenQ@Total@UnitStep[-lst],
  {30}
] // Timing

Out[]= {3.062, Null}

もっと速い方法はありますか?

4

2 に答える 2

3

これはあなたのソリューションよりも2倍強速くRule@@@、関連する用語を抽出するために使用するというナンセンスは別として、より明確であることがわかります.各記号の数要素を単純に数えます.

EvenQ[-1 /. Rule@@@Tally@Sign[lst]]

タイミング (および出力) を比較するには

In[1]:= lst=RandomReal[{-2,2},5000000];
        s=t={};
        Do[AppendTo[s,EvenQ@Total@UnitStep[-lst]],{10}];//Timing
        Do[AppendTo[t,EvenQ[-1/.Rule@@@Tally@Sign[lst]]],{10}];//Timing
        s==t
Out[3]= {2.11,Null}
Out[4]= {0.96,Null}
Out[5]= True
于 2011-03-15T04:59:46.587 に答える
1

少し遅れた投稿: 最終的に速度に関心がある場合Compile、C コンパイル ターゲットを使用すると、これまでに投稿された最速のソリューションよりも約 2 倍高速になるようです ( Tally-Signベース):

fn = Compile[{{l, _Real, 1}},
  Module[{sumneg = 0},
    Do[If[i < 0, sumneg++], {i, l}];
     EvenQ[sumneg]], CompilationTarget -> "C", 
     RuntimeOptions -> "Speed"]; 

私のマシンのタイミングは次のとおりです。

In[85]:= lst = RandomReal[{-2, 2}, 5000000];
s = t = q = {};
Do[AppendTo[s, EvenQ@Total@UnitStep[-lst]], {10}]; // Timing
Do[AppendTo[t, EvenQ[-1 /. Rule @@@ Tally@Sign[lst]]], {10}]; // Timing
Do[AppendTo[q, fn [lst]], {10}]; // Timing
s == t == q

Out[87]= {0.813, Null}

Out[88]= {0.515, Null}

Out[89]= {0.266, Null}

Out[90]= True
于 2011-03-15T10:46:26.817 に答える