【问题标题】:App for computing digits of e in c计算c中e位数的应用程序
【发布时间】:2018-06-22 08:09:48
【问题描述】:

谁能解释一下这段计算e的代码是如何工作的?对于如此复杂的任务看起来很容易,但我什至无法理解这个过程。它是由 Xavier Gourdon 于 1999 年创建的。

int main() {

  int N = 9009, a[9009], x = 0;
  for (int n = N - 1; n > 0; --n) {
      a[n] = 1;
  }
  a[1] = 2, a[0] = 0;
  while (N > 9) {
      int n = N--;
      while (--n) {
          a[n] = x % n;
          x = 10 * a[n-1] + x/n;
      }
      printf("%d", x);
  }
  return 0;
}

【问题讨论】:

    标签: c algorithm math


    【解决方案1】:

    我将算法追溯到 1995 年 Stanley Rabinowitz and Stan Wagon 的一篇论文。挺有意思的。

    先介绍一下背景。从e的普通十进制表示开始:

    e = 2.718281828...

    这可以表示为如下的无限和:

    e = 2 + 110(7 + 110(1 + 110(8 + 110(2 + 110( 8 + 110(1 ...

    显然这不是一个特别有用的表示;我们只是将相同的 e 数字包裹在一个复杂的表达式中。

    但是看看当我们用自然数的倒数替换这些 110 因子时会发生什么:

    e = 2 + 12(1 + 13(1 + 14(1 + 15(1 + 16( 1 + 17(1 ...

    这种所谓的 mixed-radix 表示为我们提供了一个序列,该序列由数字 2 和一个重复的 1 序列组成。很容易看出为什么会这样。当我们扩展括号时,我们最终得到了著名的 e 泰勒级数:

    e = 1 + 1 + 1/2! + 1/3! + 1/4! + 1/5! + 1/6! + 1/7! + ...

    那么这个算法是如何工作的呢?好吧,我们首先用混合基数 (0; 2; 1; 1; 1; 1; 1; ...) 填充一个数组。为了生成每个连续的数字,我们只需将该数字乘以 10 并吐出最左边的数字。*

    但是由于数字以混合基数形式表示,我们必须在每个数字处使用不同的基数。为此,我们从右到左工作,将第 n 位乘以 10,并将其替换为模 n 的结果值。如果结果大于或等于 n,我们将值 x/n 移动到左边的下一位。 (除以 n 将基数从 1/n! 更改为 1/(n-1)!,这就是我们想要的)。这实际上是内部循环的作用:

      while (--n) {
          a[n] = x % n;
          x = 10 * a[n-1] + x/n;
      }
    

    这里,x在程序开始时被初始化为零,而数组开始处的初始0确保每次内循环结束时它都被重置为零。结果,随着程序的运行,数组将逐渐从右侧填充零。这就是为什么 n 可以在外循环的每一步都用递减的值 N 来初始化。

    可能包含数组末尾的额外 9 位数字以防止舍入错误。运行此代码时,x 达到最大值 89671,这意味着商将跨越多个数字。

    注意事项:

    1. 这是spigot algorithm 的一种类型,因为它使用简单的整数运算输出e 的连续数字。

    2. Rabinowitz 和 Wagon 在他们的论文中指出,this algorithm was actually invented 50 years ago by A.H.J. Sale


    * 除了第一次迭代输出两位数(“27”)

    猜你喜欢
    • 1970-01-01
    • 2020-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-25
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    相关资源
    最近更新 更多