Qia*_* Li 2 wolfram-mathematica
在Mathematica中,我是否必须使用显式循环来计算给定列表中元素的乘积(可能很长)以另一个数量为模?
如果你有的话,请教你优雅的方法.谢谢!
编辑
举个例子
list=Range[2000];Mod[Product[list],32327]
Run Code Online (Sandbox Code Playgroud)
上述效率非常低,因为在计算产品时,可以采用模数来使乘数更小.
编辑2
我想我的问题涉及如何替换for循环
Module[{ret = initial_value}, For[i = 1, i <= Length[list], i++, ret = general_function[list[[i]],ret]; ret]
Run Code Online (Sandbox Code Playgroud)
给出一般功能general_function
和清单list
.
对于长名单来说,分而治之通常更快.我们的想法是计算第一和第二半的时间模型,乘以,然后取mod.
这是一个例子.我们将使用10 ^ 6个整数的列表,所有整数在0到10 ^ 10之间.
SeedRandom[1111111];
len = 6;
max = 10;
list = RandomInteger[10^max, 10^len];
Run Code Online (Sandbox Code Playgroud)
乘以并取模数,稍微大一点(我想降低结果为零的可能性):
In[119]:= Timing[Mod[Times @@ list, 32327541]]
Out[119]= {1.360000, 8826597}
Run Code Online (Sandbox Code Playgroud)
这是我描述的那种变体.试验和误差调整表明长度为2 ^ 9左右的列表最好非递归地进行,至少对于上述尺寸范围内的数字.
tmod2[ll_List, m_] := With[{len=Floor[Length[ll]/2]},
If[len<=256,
Mod[Times @@ ll, m],
Mod[tmod2[Take[ll,len],m] * tmod2[Drop[ll,len],m], m]]]
In[120]:= Timing[tmod2[list, 32327541]]
Out[120]= {0.310000, 8826597}
Run Code Online (Sandbox Code Playgroud)
当我将列表长度增加到10 ^ 7并允许从0到10 ^ 20的整数时,第一种方法需要50秒,第二种方法需要5秒.很明显,缩放对我们有利.
对于交错两个操作的迭代可能优先进行分而治之的情况,可以使用如下的折叠.
tmod3[ll_List, m_] := Fold[Mod[#1*#2,m]&, First[ll], Rest[ll]]
Run Code Online (Sandbox Code Playgroud)
虽然在长列表上与tmod2没有竞争力,但这比在调用Mod之前将所有内容相乘更快.对于长度10 ^ 7和最大元素0f 10 ^ 20,需要大约8秒来执行tmod2在5中所做的操作.