互惠回文

2021年11月30日

在YouTube上,Michael Penn证明回文的倒数之和收敛:

\PALIN}1/p中的sum_{p\

但他并没有计算总和的收敛值。

你的任务是计算无限和。完成后,欢迎您阅读建议的解决方案,或发布您自己的解决方案或在下面的评论中讨论练习。

页:1 2

5对“相互回文”的回应

  1. 您正在按大小的相反顺序将倒数相加,因此当添加下一个值时,您将收敛于一个不变的和(使用双精度时,似乎约为3.370283225788489823)。我们可以按相反的顺序生成回文(从适当小的地方开始),但可能更好的解决方案是使用Kahan求和算法(https://en.wikipedia.org/wiki/Kahan_summation_algorithm). 或者,您可以查看https://oeis.org/A118031看看答案。

  2. 使用Kahan求和的一些代码:

    #包含<矢量>#包含<cstdlib>#包括<cstdio>void nextpal(std::vector<int>&s){auto-len=s.size();对于(auto n=(len+1)/2;n>0;n--){如果(s[n-1]<9){s[len-n]=s[n-1]=s[n-1]+1;回报;}其他{s[len-n]=s[n-1]=0;}}//环绕到所有零,因此扩展s[0]=1;s.push_back(1);}双精度到双精度(std::vector<int>s){双倍x=0.0,r=1.0;//从小到大应该是准确的//这里,不需要花哨的总结。for(auto i=s.begin();i!=s.end();i++){x+=(*i)*r;r*=10.0;}返回x;}int main(int argc,char*argv[]){长计数=标准::strtol(argv[1],0,0);标准::vector<int>s={1};双和=0,和=0;双c=0;//补偿for(长i=1;;i++){如果(i%count==0){标准::printf(“%20.18f%20.18f%ld\n”,总和,总和0,i);}双y=1/t双;sum0+=y;//添加到naive sumy-=c;//减去校正双t=和+y;//添加到总和c=(t-总和)-y;//新增薪酬总和=t;//新增金额nextpal(s);}}

    还有一些输出,第一列是补偿和,第二列是“朴素”和,第三列是迭代。收敛速度较慢,因此必须运行一段时间才能与OEIS值进行比较:

    $g++-墙-O3 rpalindromes.cpp-o rpalindomes$ ./rpalindromes 100000000个3.370283197792765417 3.370283199089854076 1000000003.370283231354666675 3.370283225788489823 2000000003.370283238286138516 3.370283225788489823 3000000003.370283242340789354 3.370283225788489823 4000000003.370283245217610357 3.370283225788489823 5000000003.370283247449045838 3.370283225788489823 6000000003.370283249272261195 3.370283225788489823 7000000003.370283250813768117 3.370283225788489823 8000000003.370283252149082198 3.370283225788489823 9000000003.370283253326912476 3.370283225788489823 1000000000...
  3. 在运行了近24小时并将前万亿个倒数相加后,我们只得到了小数点后11位,但看起来求和算法正在发挥作用(https://oeis.org/A118031给出3.370283259497):

    3.370283259491198447 3.370283225788489823 9996000000003.370283259491199335 3.370283225788489823 9997000000003.370283259491200667 3.370283225788489823 9998000000003.370283259491201555 3.370283225788489823 9999000000003.370283259491202887 3.370283225788489823 1000000000000^C类

    每个小数位花费的时间大约是最后一个小数位的10倍,所以我把它停在那里,而不是一直运行到圣诞节。在代码中添加一些东西会很有趣,这些代码使用外推法来估计我们当前的收敛点。

  4. 如果将todouble()参数设置为常量引用,则速度会更快。

留下评论