2

作为我之前问题的延续,Simon 查找 PackedArray 的列表乘积的方法很快,但它不适用于负值。

这可以通过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

这比您的解决方案快两倍多一点,除了使用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 编译目标似乎比迄今为止发布的最快解决方案快两倍(基于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 回答