在Mathematica中更快地计算大整数的算术函数?

时间:2011-01-28 17:02:14

标签: wolfram-mathematica

f成为算术函数,A={k1,k2,...,kn}是递增顺序的整数。

现在,我想从k1开始,并将f(ki)f(k1)进行比较。如果f(ki)>f(k1),请将ki设为k1

现在从ki开始,将f(kj)f(ki)进行比较,j>i。如果f(kj)>f(ki),请将kj设为ki,然后重复此过程。

最后,我们将使用此属性的B={L1,...,Lm}子序列A

L1=k1
L2=ki
L3=kj
...

,其中

f(L(i+1))>f(L(i)),适用于任何1<=i<=m-1

例如,设f为整数的除数函数。

我认为应该有一些方法比我更有效率和更快。

您是否知道如何在Mathematica或Matlab中为我的目的编写代码。

Mathematica更可取。

«««««««««««««««««««««««««««««««

我已经使用Mathematica为这个程序编写了一个代码,并且需要几个小时来计算ki的f或大数的集合B.

这里我放了部分代码,这只是一个示例,我的程序中的问题可能比这些更大:

g之间的空间是产品。例如:

g [67757] g [353] = g [67757] * g [353]

««««««««««««««««««««««««««««««««««««

f[n_] := DivisorSigma[0, n];
g[n_] := Product[Prime[i], {i, 1, PrimePi[n]}];

k1 = g[67757] g[353] g[59] g[19] g[11] g[7] g[5]^2 6^3 2^7;
k2 = g[67757] g[353] g[59] g[19] g[11] g[7] g[5] 6^5 2^7;
k3 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^4 2^7;
k4 = g[67759] g[349] g[53] g[19] g[11] g[7] g[5] 6^5 2^6;
k5 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^4 2^8;
k6 = g[67759] g[349] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^7;
k7 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^5 2^6;
k8 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^4 2^9;
k9 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^7;
k10 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5] 6^5 2^7;
k11 = g[67759] g[349] g[53] g[19] g[11] g[7] g[5]^2 6^4 2^6;
k12 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^8;
k13 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^4 2^6;
k14 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^3 2^9;
k15 = g[67757] g[359] g[53] g[19] g[11] g[7] g[5]^2 6^4 2^7;
k16 = g[67757] g[359] g[53] g[23] g[11] g[7] g[5] 6^4 2^8;
k17 = g[67757] g[359] g[59] g[19] g[11] g[7] g[5] 6^4 2^7;
k18 = g[67757] g[359] g[53] g[23] g[11] g[7] g[5] 6^4 2^9;
k19 = g[67759] g[353] g[53] g[19] g[11] g[7] g[5] 6^4 2^6;
k20 = g[67763] g[347] g[53] g[19] g[11] g[7] g[5] 6^4 2^7;

k = Table[k1, k2, k3, k4, k5, k6, k7, k8, k9, k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20];

i = 1;
count = 0;
For[j = i, j <= 20, j++, 
  If[f[k[[j]]] - f[k[[i]]] > 0, i = j; Print["k",i];
   count = count + 1]];

Print["count= ", count]

««««««««««««««««««««««««««««««««««««

3 个答案:

答案 0 :(得分:6)

DivisorSigma必须考虑数字(它不知道它们是如何构建的)。你可以通过删除列表的gcd来大大提高速度。详细说明:

将新列表计算为旧列表/ gcd。

考虑gcd。

使用一个函数,在给定一对因子形式的整数的情况下,合并分解(因此你将它们的产品分解为因子形式)。

然后对于简化列表中的任何两个元素,您可以通过将它们的每个因子与gcd的因子合并进行比较,并在给定因式形式时调用一个函数来计算除数的数量。最后一个只是指数的乘积,每个都增加了一个。

在代码中:

kgcd = GCD @@ k;
newk = k/kgcd;
gcdfacs = FactorInteger[kgcd];

sumDivisors[faclist_] := Times @@ (1 + faclist[[All, 2]])

mergeFactorLists[fl1_, fl2_] := 
 Flatten[GatherBy[Join[fl1, fl2], First] /.
{{p1_Integer,e1_Integer}, {p1_,e2_Integer}} -> {{p1,e1+e2}}, 1]

f2[v1_] := sumDivisors[mergeFactorLists[FactorInteger[v1], gcdfacs]]

以下是您的示例,其中f2应用于newk的元素。

Timing[i = 1;
  count = 0;
  For[j = i, j <= 20, j++,
    If[f2[newk[[j]]] - f2[newk[[i]]] > 0, i = j; Print["k", i];
      count = count + 1]];
  Print["count= ", count]]

评估In [140]时:= k2

评估In [140]时:= k5

评估In [140]时:= k7

评估In [140]时:= k8

评估In [140]时:= k9

评估In [140]时:= k10

评估In [140]时:= k12

评估In [140]时:= k13

评估In [140]时:= k14

评估In [140]时:= k15

评估In [140]时:= k16

评估In [140]时:= k17

评估In [140]时:= k18

在评估In [140]期间:= count = 13

Out [140] = {0.539918,Null}

正如其他人评论的那样,你可能想要做SortBy或者

sortedk = k[[Ordering[newk, All, f2[#1] < f2[#2] &]]];

- 更新2011-02-01 -

以下是各种请求函数,用于对表示为其素因子和相应幂的列表的整数进行操作。我们使用效用函数来“乘”两个或更多这样的表示,以便它们可以从上面g []的定义中轻松构造。

logarithm [fl_]:= fl [[All,2]]。登录[FL [[全部,1]]]

divSigma[k_, fax_] := Times @@
  ((fax[[All, 1]]^(k*(fax[[All, 2]] + 1)) - 1)/(fax[[All, 1]]^k - 1))

mergeFactorLists[f1_,f2_,f3__] := 
  mergeFactorLists[mergeFactorLists[f1,f2],f3]

mergeFactorLists[fl1_, fl2_] := 
  Flatten[GatherBy[Join[fl1, fl2], First] /.
    {{p1_Integer,e1_Integer}, {p1_,e2_Integer}} -> {{p1,e1+e2}}, 1]

eulerPhi[fl_] := 
 Times @@ ((fl[[All, 1]] - 1)*fl[[All, 1]]^(fl[[All, 2]] - 1))

我以类似于上面使用g []的方式使用factorlist,但是为了获得因式列表而不是整数本身。为了便于转换代码,您可以执行以下操作。

g[n__] := factorList[n]

然后你将构建k1等作为:

k1 = mergeFactorLists[g[67757], g[353], g[59], g[19], g[11], g[7], 
  g[5, 2], g[4, 3], g[2, 7]];

我注意到使用索引可能更好,例如k [1],k [2]等。这种方式可以存储索引而不是数字(无论是表示为因子列表还是完全展开)。这是您的评论或私人电子邮件中的一个问题,我不确定。

这是一个简短的例子,表明这些功能可能与广告一样有效。

在[77]中:= example =       mergeFactorLists [g [59],g [19],g [11],g [7],g [5,2],g [4,3],g [2,7]] Out [77] = {{2,16},{3,9},{5,6},{7,4},{11,3},{13,2},{17,   2},{19,2},{23,1},{29,1},{31,1},{37,1},{41,1},{43,   1},{47,1},{53,1},{59,1}}

在[83]中:= divSigma [2,示例] 出[83] = 8309625653259163198663074449058595410045270294408417958734031 0136565010401600000000

在[92]中:= eulerPhi [例子] 出[92] = 30117106786279162451552137484697600000000

在[95]中:= examplenumber = Times @@ Map [#[[1]] ^#[[2]]&amp ;, example] 出[95] = 225123336762006539948611826706656256000000

在[99]中:= DivisorSigma [2,examplenumber] 出[99] = 8309625653259163198663074449058595410045270294408417958734031 0136565010401600000000

在[100]中:= EulerPhi [examplenumber] Out [100] = 30117106786279162451552137484697600000000

- 结束更新 -

Daniel Lichtblau Wolfram Research

答案 1 :(得分:1)

在我的mathematica版本中,大部分计算时间都花在应用函数f [n]上。即使只是f [k1]也需要几秒钟。

无论如何,您要做的是使用SortBy。这将采用列表和函数作为参数。它将函数应用于列表的每个成员,并按从最小到最大的顺序对它们进行排序,因此您需要将列表交换为最大到最小。记得使用k = List [k1,k2,...,k20]而不是k = Table [k1,k2,...,k20],你应该很好。

答案 2 :(得分:0)

之所以这么慢,部分原因是因为你在Mathematica中使用for和if。两者都不是特别快。

通常建议尝试进行一些列表操作,因为这样会更快。我不确定你是如何做到这一点的,但你可能想要研究一下。