如何编写将 pi (π) 返回给定小数位数的函数?
速度不是问题。我一直在看http://bellard.org/pi/,但我仍然不明白如何获得 pi 的第 n 位数字。
如何编写将 pi (π) 返回给定小数位数的函数?
速度不是问题。我一直在看http://bellard.org/pi/,但我仍然不明白如何获得 pi 的第 n 位数字。
在微积分中有一个叫做泰勒级数的东西,它提供了一种简单的方法来计算许多无理值到任意精度。
Pi/4 = 1 - 1/3 + 1/5 - 1/7 + ...
(来自http://www.math.hmc.edu/funfacts/files/30001.1-3.shtml)
继续添加这些术语,直到您想要稳定的精度位数。
泰勒定理是一个强大的工具,但是使用该定理推导这个级数超出了问题的范围。这是标准的大学一年级微积分,如果您对更多细节感兴趣,可以很容易地在谷歌上搜索。
我并不是要暗示这是计算 pi 最实用的方法。这将取决于你为什么真的需要这样做。出于实际目的,您应该从众多已发布版本之一中复制所需数量的数字。我建议这是对非理性值如何等同于无限级数的简单介绍。
尝试“以 O(n^2) 为基数计算 pi 的第 n 位数字”。它可能是已知最快的算法,不需要任意(读取巨大)精度浮点数,并且可以直接以 10 为底(或任何其他)为您提供结果。
作为 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;
}
}
我相信您正在寻找的算法就是所谓的“Spigot 算法”。一种特殊的类型是BBP (Bailey-Borwein-Plouffe) 公式。
我相信这就是你要找的。
“曼德布罗集中的 π ”探讨了复平面上一系列点之间的奇怪关系,以及如何计算它们的“曼德布罗数”(因为缺乏更好的术语……确定序列中的点所需的迭代次数)不是 Mandelbrot 集的成员)与 PI 相关。
实际的?可能不是。
出乎意料和有趣?我认同。
我会从公式开始
pi = 16 arctan (1/5) - 4 arctan (1/239)
谷歌很容易找到这个公式的证明,正常人可以理解,以及计算反正切函数的公式。这将使您可以轻松快速地计算出几千位十进制数字。
由于您没有明确指定您的函数必须计算值,因此如果您愿意对其可以“计算”的位数设置上限,那么这是一个可能的解决方案:
// 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 值同样快速地尖叫。
我的两分钱……这可能不是最快的,但我认为这很容易理解。我是在一次数学课上自己想出来的,在文学的其他地方我还没有真正看到过。要么我是个天才,真的很愚蠢,要么真的不注意阅读有关数学的书籍,或者以上所有... :)
无论如何...从单位圆开始。我们知道x^2+y^2=1,所以y=sqrt(1-x^2)。我们也知道单位圆的面积是 PI。如果我们现在取函数 sqrt(1-x^2) 在 0 到 1 范围内的积分,我们将得到 PI 的四分之一。所以乘以 4 得到 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 个正确的小数。不是最有效的,但它是我的宝贝...... :)
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;
};
我能够计算出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;
}
实际上有一个很好的解释我使用的系列是如何在这里派生的,我强烈建议你观看。
import math
def pi(x):
for i in range(1,x):
print( (360.0*math.tan(math.radians(1/(2*i))))/(1/i))
就像通过获得最小的可能一样,然后我使用该角度来计算编号。的边。
然后使用三角法计算边的长度......您也可以将 替换math.tan
为math.sin
。