用C ++实现Bailey-Borwein-Plouffe公式?

时间:2011-09-01 02:57:46

标签: c++ pi

编辑:要求是模糊的,而不是计算pi的第n位数,他们只是希望pi到第n位不超出浮点数限制,所以蛮力方式适用于要求。

我需要计算第n个数字的PI,我想尝试使用BBP formula但遇到困难。我输入的等式似乎没有正确地给我PI。

(1 / pow(16,n))((4 / (8 * n + 1)) - (2 / (8 * n + 4)) - (1 / (8 * n + 5)) - (1 / (8 * n + 6)))

我成功地使用蛮力的方式找到PI,但这只是如此准确,找到第n个数字是困难的。

(4 - (4/3) + (4/5) - (4/7)...)

我想知道是否有人对如何做到这一点有更好的了解,或者可能对我的BBP方程有所帮助?

谢谢你,
LF4

功能性但不是非常准确,直到几次迭代,然后你必须取消最后几次。

#include <iostream>

using namespace std;

int main()
{
    int loop_num = 0;
    cout << "How many digits of pi do you want?: ";
    cin  >> loop_num;

    double my_pi = 4.0;
    bool add_check = false;
    int den = 3;
    for (int i = 0; i < loop_num; i++)
    {
        if (add_check)
        {
            my_pi += (4.0/den);
            add_check = false;
            den += 2;
        }
        else
        {
            my_pi -= (4.0/den);
            add_check = true;
            den += 2;
        }
    }
    cout << "Calculated PI is: " << my_pi << endl;
    system("pause");

    return 0;
}

我希望这是一个更好的计划。

#include <iostream>
#include <cmath>

using namespace std;

const double PI_BASE = 16.0;

int main()
{
    int loop_num = 0;
    cout << "How many digits of pi do you want?: ";
    cin  >> loop_num;

    double my_pi = 0.0;
    for (int i = 0; i <= loop_num; i++)
    {
        my_pi += ( 1.0 / pow(PI_BASE,i) )( (4.0 / (8.0 * i + 1.0)) -
                                           (2.0 / (8.0 * i + 4.0)) -
                                           (1.0 / (8.0 * i + 5.0)) -
                                           (1.0 / (8.0 * i + 6.0)) );
    }
    cout << "Calculated PI is: " << my_pi << endl;
    system("pause");

    return 0;
}

3 个答案:

答案 0 :(得分:5)

无论您使用什么公式,您都需要任意精度算术才能获得超过16位数。 (因为“double”只有16位精度)。

Chudnovsky公式是计算Pi的最快已知公式,每学期收敛14位数。但是,有效实施起来非常困难。

由于此公式的复杂性,使用计算Pi的数量少于几千位是没有意义的。所以不要使用它,除非你准备好用任意精度算法全力以赴。

使用GMP库的Chudnovsky公式的良好开源实现在这里:http://gmplib.org/pi-with-gmp.html

答案 1 :(得分:4)

当BBP公式主要用于计算π的任意十六进制数字时,您似乎正在尝试计算π的十进制数字。基本上,BBP公式可以用来计算π的 n th 十六进制数字而不计算前面的数字,十六进制数字0,1,..., n - 1。

David H. Bailey(Bailey-Borwein-Plouffe的Bailey)写了C and Fortran code来计算使用BBP的π的 n th 十六进制数字式。在具有IEEE 754双算术的机器上,从0开始计算精确到 n ≈1.18×10 7 ;即π=(3.243F6A8 ...) 16 所以当 n = 3时程序的输出以“F”开头:

 position = 3
 fraction = 0.963509103793105
 hex digits =  F6A8885A30

我喜欢稍微修改C版本,以便命令行参数可以覆盖 n (代码中名为id):

--- piqpr8.c.orig   2011-10-08 14:54:46.840423000 -0400
+++ piqpr8.c    2011-10-08 15:04:41.524437000 -0400
@@ -14,14 +14,18 @@
 /*  David H. Bailey     2006-09-08 */

 #include <stdio.h>
+#include <stdlib.h>
 #include <math.h>

-main()
+int main(int argc, char *argv[])
 {
   double pid, s1, s2, s3, s4;
   double series (int m, int n);
   void ihex (double x, int m, char c[]);
   int id = 1000000;
+  if (argc == 2) {
+    id = atoi(argv[1]);
+  }
 #define NHX 16
   char chx[NHX];

@@ -36,6 +40,8 @@
   ihex (pid, NHX, chx);
   printf (" position = %i\n fraction = %.15f \n hex digits =  %10.10s\n",
   id, pid, chx);
+
+  return EXIT_SUCCESS;
 }

 void ihex (double x, int nhx, char chx[])

答案 2 :(得分:4)

BBP公式不适合轻松查找第n个十进制数字,因为它很容易返回十六进制数字,只返回十六进制数字。因此,要重新计算为小数,您需要收集所有十六进制数字。

使用牛顿公式要好得多:

Pi / 2 = 1 + 1/3 + 1 * 2/3 * 5 + 1 * 2 * 3/3 * 5 * 7 + .... n!/(2n + 1)!! + ....

它崩溃到霍纳的计划:

Pi / 2 = 1 + 1/3 *(1 + 2/5 *(1 + 3/7 *(1 + ...... n /(2n + 1)*(1)... ..)))

所以你把Pi写成一个位置序列,在每个分数位置你使用不同的基数(n /(2n + 1)),所有数字都等于2.它明显收敛,因为该基数小于1/2,所以要计算Pi到n个有效小数dgits,你需要的不超过log_2(10)* n个项(N = 10 * n / 3 + 1是完美的东西)。

从N个整数元素的数组开始,全部等于2,重复n次,执行以下操作:

1。)将所有元素乘以10。

2。)重新计算每个元素[k](从N下降到1),使得“数字”小于分母(2 * k + 1),但同时你需要移动一个qoutient到左侧位置,所以:
  q =元素[k] /(2 * k + 1);
  element [k]%=(2 * k + 1);
  元素[k-1] + = q * k; // k是计数器,所以不要忘记乘法。

3。)取元素[0]。它等于10 *第一个数字,因此您需要输出元素[0] / 10     并存储
元素[0]%= 10;

但是有一个线索:牛顿公式的最大可能数字(2 * n)的最大和是2.所以你可以从元素[1]获得多达19/10。当添加到元素[0](在步骤1中乘以10)时,您可以获得90 + 19 = 109。所以它有时会发生输出数字[10]。在这种情况下,您知道正确的数字是0,并且必须将1添加到先前输出的数字。

有两种方法可以解决这个问题:

1。)在计算下一个数字之前不输出最后一个数字。此外,存储连续9的数量并将它们输出为9或1,然后输出0,具体取决于非9位数。

2。)将输出的数字放入结果数组中,如果[10]发生,你可以轻松添加1。

在我的电脑上,我可以在10秒内计算(以Java格式)10,000个十进制数字。复杂度为O(n ^ 2)。

元素[k]的值永远不会超过12 * k,因此在快速机器上使用64位长类型,您可以计算超过10 ^ 15位数(非常强大的数字)。