为什么我计算 pi 数的函数冻结了?
Why my function that calculates pi number is freezing?
我需要计算 pi
数字直到第 15 位,但我的函数冻结了。我使用这个泰勒级数:
atan(x) = \sum_{n=0}^\infty \frac{(-1)^{n} \cdot x^{2n + 1}}{2n + 1}
x 等于 1。
有我的功能:
public static decimal Pi()
{
decimal curr = 4m,
prev = 0m,
one = -1m,
den = 3.0m;
while (Math.Abs(curr - prev) > 1e-15m)
{
prev = curr;
curr += 4.0m * one / den;
one = -one;
den += 2.0m;
}
return curr;
}
调试了,没找到原因。 Link 至 REPL
问题是该算法在您想要的精度位数方面呈指数增长。为了演示,在我们得到越来越精确的结果之前,我已经稍微更改了您的代码以跟踪迭代次数
decimal curr = 4m,
prev = 0m,
one = -1m,
den = 3.0m;
int i = 0;
decimal epsilon = 1;
while(true)
{
prev = curr;
curr += 4.0m * one / den;
one = -one;
den += 2.0m;
i++;
if(Math.Abs(curr - prev) <= epsilon)
{
Console.WriteLine(curr);
Console.WritleLine(i);
epsilon /= 10m;
}
}
这是达到 8 位精度后的结果输出。
3.4666666666666666666666666667
2
3.1891847822775947292439110472
20
3.1465677471829564012877876609
200
3.1420924036835276076022995132
2000
3.1416426510898869869000847891
20000
3.1415976535647933322124871234
200000
3.1415931535895432385563933310
2000000
3.1415927035897907384627370503
20000000
3.1415926585897932134626435385
200000000
如您所见,每个额外的精度数字需要 10 倍的迭代次数,因此 15 个数字将花费 10,000,000 次,只要它得到 8 个数字。
根据公式,
|cur - prev| = 1 / (2n+1) + 1 / (2n-1)
你的函数应该可以正常工作,你只需要等到第 250,000,000,000,000 个任期。有点耐心(只有几天)。
但不能保证你最后得到15个准确的数字。
永远不要使用莱布尼茨的公式。使用 Machin 的变体。 https://en.wikipedia.org/wiki/Machin-like_formula
我需要计算 pi
数字直到第 15 位,但我的函数冻结了。我使用这个泰勒级数:
atan(x) = \sum_{n=0}^\infty \frac{(-1)^{n} \cdot x^{2n + 1}}{2n + 1}
x 等于 1。
有我的功能:
public static decimal Pi()
{
decimal curr = 4m,
prev = 0m,
one = -1m,
den = 3.0m;
while (Math.Abs(curr - prev) > 1e-15m)
{
prev = curr;
curr += 4.0m * one / den;
one = -one;
den += 2.0m;
}
return curr;
}
调试了,没找到原因。 Link 至 REPL
问题是该算法在您想要的精度位数方面呈指数增长。为了演示,在我们得到越来越精确的结果之前,我已经稍微更改了您的代码以跟踪迭代次数
decimal curr = 4m,
prev = 0m,
one = -1m,
den = 3.0m;
int i = 0;
decimal epsilon = 1;
while(true)
{
prev = curr;
curr += 4.0m * one / den;
one = -one;
den += 2.0m;
i++;
if(Math.Abs(curr - prev) <= epsilon)
{
Console.WriteLine(curr);
Console.WritleLine(i);
epsilon /= 10m;
}
}
这是达到 8 位精度后的结果输出。
3.4666666666666666666666666667
2
3.1891847822775947292439110472
20
3.1465677471829564012877876609
200
3.1420924036835276076022995132
2000
3.1416426510898869869000847891
20000
3.1415976535647933322124871234
200000
3.1415931535895432385563933310
2000000
3.1415927035897907384627370503
20000000
3.1415926585897932134626435385
200000000
如您所见,每个额外的精度数字需要 10 倍的迭代次数,因此 15 个数字将花费 10,000,000 次,只要它得到 8 个数字。
根据公式,
|cur - prev| = 1 / (2n+1) + 1 / (2n-1)
你的函数应该可以正常工作,你只需要等到第 250,000,000,000,000 个任期。有点耐心(只有几天)。
但不能保证你最后得到15个准确的数字。
永远不要使用莱布尼茨的公式。使用 Machin 的变体。 https://en.wikipedia.org/wiki/Machin-like_formula