37

如何编写将 pi (π) 返回给定小数位数的函数?

速度不是问题。我一直在看http://bellard.org/pi/,但我仍然不明白如何获得 pi 的第 n 位数字。

4

11 回答 11

31

在微积分中有一个叫做泰勒级数的东西,它提供了一种简单的方法来计算许多无理值到任意精度。

Pi/4 = 1 - 1/3 + 1/5 - 1/7 + ...
(来自http://www.math.hmc.edu/funfacts/files/30001.1-3.shtml

继续添加这些术语,直到您想要稳定的精度位数。

泰勒定理是一个强大的工具,但是使用该定理推导这个级数超出了问题的范围。这是标准的大学一年级微积分,如果您对更多细节感兴趣,可以很容易地在谷歌上搜索。


我并不是要暗示这是计算 pi 最实用的方法。这将取决于你为什么真的需要这样做。出于实际目的,您应该从众多已发布版本之一中复制所需数量的数字。我建议这是对非理性值如何等同于无限级数的简单介绍。

于 2010-04-16T16:59:59.510 回答
7

尝试“以 O(n^2) 为基数计算 pi 的第 n 位数字”。它可能是已知最快的算法,不需要任意(读取巨大)精度浮点数,并且可以直接以 10 为底(或任何其他)为您提供结果。

于 2010-04-16T18:32:20.820 回答
6

作为 JeffH 存储每个变化的方法的替代方法,您可以只存储最大位数并删除不需要的内容:

#include <string>
#include <iostream>
using std::cout; using std::endl; using std::string;

// The first 99 decimal digits taken from:
// http://www.geom.uiuc.edu/~huberty/math5337/groupe/digits.html
// Add more as needed.
const string pi =
  "1415926535"
  "8979323846"
  "2643383279"
  "5028841971"
  "6939937510"
  "5820974944"
  "5923078164"
  "0628620899"
  "8628034825"
  "342117067";

// A function in C++ that returns pi to X places
string CalcPi(const size_t decimalDigitsCount) 
{
  string returnValue = "3";
  if (decimalDigitsCount > 0)
  {
    returnValue += "." + pi.substr(0, decimalDigitsCount);
  }
  return returnValue;
} 

int main()
{
  // Loop through all the values of "pi at x digits" that we have. 
  for (size_t i = 0; i <= pi.size(); ++i) 
  {
    cout << "pi(" << i << "): " << CalcPi(i) << endl;
  } 
}

http://codepad.org/6mqDa1zj

于 2010-04-16T19:01:02.357 回答
6

我相信您正在寻找的算法就是所谓的“Spigot 算法”。一种特殊的类型是BBP (Bailey-Borwein-Plouffe) 公式。

我相信这就是你要找的。

于 2010-04-20T13:32:13.570 回答
3

曼德布罗集中的 π ”探讨了复平面上一系列点之间的奇怪关系,以及如何计算它们的“曼德布罗数”(因为缺乏更好的术语……确定序列中的点所需的迭代次数)不是 Mandelbrot 集的成员)与 PI 相关。

实际的?可能不是。

出乎意料和有趣?我认同。

于 2010-04-16T20:31:20.350 回答
3

我会从公式开始

pi = 16 arctan (1/5) - 4 arctan (1/239)

谷歌很容易找到这个公式的证明,正常人可以理解,以及计算反正切函数的公式。这将使您可以轻松快速地计算出几千位十进制数字。

于 2014-08-27T23:35:11.180 回答
2

你愿意查找值而不是计算它们吗?

由于您没有明确指定您的函数必须计算值,因此如果您愿意对其可以“计算”的位数设置上限,那么这是一个可能的解决方案:

// Initialize pis as far out as you want. 
// There are lots of places you can look up pi out to a specific # of digits.
double pis[] = {3.0, 3.1, 3.14, 3.141, 3.1416}; 

/* 
 * A function that returns pi out to a number of digits (up to a point)
 */
double CalcPi(int x)
{
    // NOTE: Should add range checking here. For now, do not access past end of pis[]
    return pis[x]; 
}

int main()
{
    // Loop through all the values of "pi at x digits" that we have.
    for (int ii=0; ii<(int)sizeof(pis)/sizeof(double); ii++)
    {
        double piAtXdigits = CalcPi(ii);
    }
}

以这种方式编写 CalcPi() (如果它满足您的需要)有一个附带好处,即对于您上限内的任何 X 值同样快速地尖叫。

于 2010-04-16T17:52:10.353 回答
1

我的两分钱……这可能不是最快的,但我认为这很容易理解。我是在一次数学课上自己想出来的,在文学的其他地方我还没有真正看到过。要么我是个天才,真的很愚蠢,要么真的不注意阅读有关数学的书籍,或者以上所有... :)

无论如何...从单位圆开始。我们知道x^2+y^2=1,所以y=sqrt(1-x^2)。我们也知道单位圆的面积是 PI。如果我们现在取函数 sqrt(1-x^2) 在 0 到 1 范围内的积分,我们将得到 PI 的四分之一。所以乘以 4 得到 PI:

PI公式

如果我们试图通过分析解决这个问题,我相信我们只会找回 PI。但是编写一个程序来解决它是很容易的。以下是C语言:

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

void main(void) {
    double interval=0.0000001,area=0,x,y;

    for (x=0; x<1; x+=interval)
        area+=4*interval*sqrt(1-x*x);

    printf("pi ~ %.20f\n",area);
}

使用上述设置运行它interval,我们得到:

pi ~ 3.14159285415672595576

所以 10,000,000 次迭代给出 6 个正确的小数。不是最有效的,但它是我的宝贝...... :)

于 2018-11-28T08:51:38.853 回答
0
pi = function () {
    let pi = 3;
    let a = 3;
    let even = false;
    let turn;

    while (a <= 90000) {
        turn = (4/((Math.pow(a, 3)) - (a)));

        if(even){
            turn = turn*-1;
            even = false;
        } else {
            even = true;
        }
        pi = pi + turn;
        a = a + 2;
    }
    return pi;
};
于 2017-11-23T15:29:01.290 回答
0

我能够计算出PI接近实际的圆周率。这是它的c++实现。

#include <iostream>
#include <iomanip>
#include <cmath>

using namespace std;

long double calPI(long iterations = 1000)
{
    long double pi = 0.0, factor = 1;
    long i;
    for (i = 2; i < iterations; i += 2, factor *= -1)
    {
        pi += factor / (i - 1.0);
    }
    return 4 * pi;
}
// 3.14159265358979323846264338327950288419716939937510          -> Actual (50 digits)
// 3.141592653589793115997963468544185161590576171875            -> From acos
// 3.14159265452113118342880593303334535448811948299407958984375 -> Calculated
int main()
{
    int digits;
    long double PI;
    cout << "Enter how many digits of precision you want to have : ";
    cin >> digits;
    PI = calPI(2147453647); // By far the maximum precision I was able to reach
    cout << "The value of pi upto " << digits << " digits : " << setprecision(digits) << PI << endl;
    cout << "Actual value of pi from math.h : " << 2 * acos(0.0) << endl;
    return 0;
}

实际上有一个很好的解释我使用的系列是如何在这里派生的,我强烈建议你观看。

于 2021-10-11T08:57:30.823 回答
-1
import math
def pi(x):
    for i in range(1,x):
        print( (360.0*math.tan(math.radians(1/(2*i))))/(1/i))

就像通过获得最小的可能一样,然后我使用该角度来计算编号。的边。

然后使用三角法计算边的长度......您也可以将 替换math.tanmath.sin

于 2020-07-30T10:02:57.677 回答