Быстрый список-знак продукта для PackedArray? - PullRequest
2 голосов
/ 15 марта 2011

Как продолжение моего предыдущего вопроса , метод Саймона для нахождения продукта списка в PackedArray быстрый, но он не работает с отрицательными значениями.

Это может быть "исправлено""на Abs с минимальными затратами времени, но знак утерян, поэтому мне нужно будет найти знак продукта отдельно.

Самый быстрый метод, который я пробовал - EvenQ @ Total @ UnitStep[-lst]

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

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

Out[]= {3.062, Null}

Есть ли более быстрый путь?

Ответы [ 2 ]

3 голосов
/ 15 марта 2011

Это чуть более чем в два раза быстрее, чем ваше решение, и кроме бессмысленного использования 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
1 голос
/ 15 марта 2011

Немного запоздалое сообщение: если вы в конечном итоге заинтересованы в скорости, Compile с целью компиляции C, кажется, примерно в два раза быстрее, чем самое быстрое решение, опубликованное до сих пор (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
...