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

Wolfram mathematica 在Mathematica中计算大整数的算术函数更快?,wolfram-mathematica,Wolfram Mathematica,设f是一个算术函数,A={k1,k2,…,kn}是递增的整数 现在我想从k1开始,比较fki和fk1。如果fki>fk1,则将ki设为k1 现在从ki开始,比较fkj和fki,因为j>i。如果fkj>fki,则将kj设为ki,并重复此步骤 最后,我们将通过以下属性得到a的子序列B={L1,…,Lm}: L1=k1 L2=ki L3=kj ... 在哪里 fLi+1>fLi,对于任何一个来说,它之所以如此缓慢的部分原因是因为你在Mathematica中使用了for's和if's。两者都不是特别快

设f是一个算术函数,A={k1,k2,…,kn}是递增的整数

现在我想从k1开始,比较fki和fk1。如果fki>fk1,则将ki设为k1

现在从ki开始,比较fkj和fki,因为j>i。如果fkj>fki,则将kj设为ki,并重复此步骤

最后,我们将通过以下属性得到a的子序列B={L1,…,Lm}:

L1=k1
L2=ki
L3=kj
...
在哪里


fLi+1>fLi,对于任何一个来说,它之所以如此缓慢的部分原因是因为你在Mathematica中使用了for's和if's。两者都不是特别快


通常,建议尝试执行一些列表操作,因为这要快得多。我不确定你如何能马上完成这项工作,但你可能想研究一下。

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


通常,建议尝试执行一些列表操作,因为这要快得多。我不确定你如何能马上完成这项工作,但你可能想研究一下。

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


在任何情况下,你想做的就是使用。这将以列表和函数作为参数。它将函数应用于列表中的每个成员,并按从最小到最大的顺序对它们进行排序,因此您需要将列表从最大到最小进行交换。记住用k=List[k1,k2,…,k20]代替k=Table[k1,k2,…,k20],你应该很好。

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


在任何情况下,你想做的就是使用。这将以列表和函数作为参数。它将函数应用于列表中的每个成员,并按从最小到最大的顺序对它们进行排序,因此您需要将列表从最大到最小进行交换。记住用k=List[k1,k2,…,k20]代替k=Table[k1,k2,…,k20],你应该做得很好。

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

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]中:=示例= 合并因子列表[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,示例] Out[83]=83096256532591631986630744905959541045270294408417958734031\ 01365650104160000000

在[92]:=eulerPhi[示例] Out[92]=30111067862791621624515521374846976000000

在[95]:=examplenumber=Times@@Map[[[1]]^[[2]]&,示例] Out[95]=22523336762006539948611826706656256000000

在[99]中:=除数符号[2,examplenumber] Out[99]=83096256532591631986630744905959541045270294408417958734031\ 01365650104160000000

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

-结束更新-

丹尼尔·利奇布劳
Wolfram Research

DivisorSigma必须考虑数字,但它不知道这些数字是如何构造的。通过删除列表中的gcd,可以大大加快这一速度。详细内容:

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

考虑gcd

使用一个函数,给定一对分解形式的整数,合并分解,使其乘积为分解形式

然后,对于简化列表中的任意两个元素,您可以通过合并它们各自的因子分解与gcd的因子分解进行比较,并调用函数计算给定因子形式时的因子数。最后一个就是每增加一个b的指数的乘积 是的

代码:

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

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]中:=示例= 合并因子列表[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,示例] Out[83]=83096256532591631986630744905959541045270294408417958734031\ 01365650104160000000

在[92]:=eulerPhi[示例] Out[92]=30111067862791621624515521374846976000000

在[95]:=examplenumber=Times@@Map[[[1]]^[[2]]&,示例] Out[95]=22523336762006539948611826706656256000000

在[99]中:=除数符号[2,examplenumber] Out[99]=83096256532591631986630744905959541045270294408417958734031\ 01365650104160000000

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

-结束更新-

丹尼尔·利奇布劳
Wolfram Research(Wolfram Research)

可以展示你已经做了什么?不要忘记格式化你的代码,请展示你已经做了什么?不要忘记格式化你的代码,请至少使用Do循环,而不是For循环,如果你想保留命令式风格。如果你想保留命令式风格,至少应该使用Do循环而不是For循环。它们的速度要快得多。@Daniel注意,排序方法返回的当然是一个包含20项的列表,而OP的方法返回13项。我认为OP的排序是有缺陷的,除非他不想对列表排序。我想问题不是很清楚。@belisarius和asd我也不确定结果应该是什么。对于子序列,我想像Reap[For[…Sow…]…]这样的构造是最好的。@asd您可以对较大的数据集使用这种方法。关键是将这些值保持在素数及其相关非零幂的分解形式列表中。DivisorSigma函数是乘法函数,因此从数字n的这种形式很容易获得与DivisorSigma[k,n]相同的值,并且代码适中。它将比DivisorSigma快得多,因为它首先必须考虑其输入。关于n*Log[n]分母,在大多数情况下,可以使用低精度数值近似。只有在精度较低的情况下出现平局时,才需要使用全精度。@asd您可以定义自己的除数sigma函数,以采用整数的分解形式,如下所示。我将k=3,n=6666与内置除数sigma进行比较。你可以打电话给我danl@wolfram.com在[43]:=divSigma[k,fax]:=Times@@fax[[All,1]]^k*fax[[All,2]+1-1/fax[[All,1]]^k-1In[44]:=divSigma[3,FactorInteger[6666]]Out[44]=345835290528 In[36]:=divisiorsigma[3666]Out[36]=345835290528aacck。有谁能告诉我如何使用换行符/回车/回车来发表评论吗?要在字母和键盘对比度有限的HP笔记本电脑上格式化,而不因使用回车符来表示行距而过早发布评论,已经非常困难了。“我在常见问题解答中没有看到答案,如果我错过了,请道歉。@Daniel注意,您的排序方法当然会返回一个包含20项的列表,而OP的方法返回13项。”。我认为OP的排序是有缺陷的,除非他不想对列表排序。我想问题不是很清楚。@belisarius和asd我也不确定结果应该是什么。对于子序列,我想像Reap[For[…Sow…]…]这样的构造是最好的。@asd您可以对较大的数据集使用这种方法。关键是将这些值保持在素数及其相关非零幂的分解形式列表中。DivisorSigma函数是乘法函数,因此从数字n的这种形式很容易获得与DivisorSigma[k,n]相同的值,并且代码适中。它将比DivisorSigma快得多,因为它首先必须考虑其输入。关于n*Log[n]分母,在大多数情况下,可以使用低精度数值近似。只有在精度较低的情况下出现平局时,才需要使用全精度。@asd您可以定义自己的除数sigma函数,以采用整数的分解形式,如下所示。我将k=3,n=6666与内置除数sigma进行比较。你可以打电话给我danl@wolfram.com在[43]:=divSigma[k,fax]:=Times@@fax[[All,1]]^k*fax[[All,2]]+1
-1/传真[[All,1]]^k-1In[44]:=divSigma[3,FactorInteger[6666]]Out[44]=345835290528 In[36]:=divisiorsigma[3666]Out[36]=345835290528aacck。有谁能告诉我如何使用换行符/回车/回车来发表评论吗?要在字母和键盘对比度有限的HP笔记本电脑上格式化,而不因使用回车符来表示行距而过早发布评论,已经非常困难了。我在常见问题解答中没有看到这个问题的答案,如果我错过了,请道歉。