我在C(PI计算)中编写了非常简单的程序,我得到了这样的结果: 3.1406174152499528235728265546100601568468846380710601806640625
结果看起来不像正确的PI然后我在互联网上的Python中找到了代码我跑了它并得到了类似的东西: 3.1415926535897932384626433832795028841971693993751058209749 - 正确的PI。
然后我以完全相同的方式在C中实现了Python算法,我得到了这样的结果: 3.1406174152499528235728265546100601568468846380710601806640625
为什么结果形式Python和C来自同一算法是如此不同以及如何修复C代码以获得正确的结果?
Python代码:
from decimal import*
precision = 100
getcontext().prec = 100
a = 1
b = Decimal(1) / Decimal(2).sqrt()
t = Decimal(1) / Decimal(4)
p = 1
pi = 0
for x in range(0, precision):
nextA = (a + b) / 2
nextB = (a * b).sqrt()
nextT = t - p * ((a - nextA) ** 2)
nextP = 2 * p
pi = ((a + b) ** 2) / (4 * t)
a,b,t,p = nextA,nextB,nextT,nextP
print pi
C代码:
long double a = 1;
long double b = 1/sqrt(2);
long double t = 0.25;
long double p = 1;
long double an, bn, tn, pn, myPI;
long int x;
for(x = 0; x < 100; x++)
{
an = (a + b) / 2;
bn = sqrt(a * b);
tn = t - p * ((a - an) * (a - an));
pn = 2 * p;
myPI = ((a + b) * (a + b)) / (4 * t);
a = an; b = bn; t = tn; p = tn;
}
printf("%.61Lf\n", myPI);
return 0;
答案 0 :(得分:8)
问题是代码中的拼写错误,p = tn;
应为p = pn;
。
注意:对于长双打,请使用sqrtl
。
更新:如果你在每次迭代后打印出pi的近似值,那么在第五次迭代之后它并没有变得更好,只有前20个数字是正确的。为了获得更高的精度,您需要更好的(不是内置的)数据类型。
答案 1 :(得分:6)
您要求的精度高于C浮点变量所能提供的精度。您需要使用任意精度算术而不是固定精度浮点。或者至少使用固定精度算术,其精度值大于您所需的计算精度。 Python代码将精度设置为100来实现此目的。
嗯,@ yi_H也在你的代码中发现了一个错误,但是即使你修复了这个错误,你也不会得到与C代码相同的精度,因为上面的原因。
答案 2 :(得分:0)
原因是浮点数(通常为80位)是C必须提供的最精确的数字数据类型,对于大多数实际计算来说,这已经足够了(OTOH)一个浮动,无论多大,都不能完全代表0.85,但除此之外。
Python有一个内置的大整数类型,它允许它代表任意大的整数(并且,在这个实现上捎带,任意精确的有理数)。通过使用这些,可以计算PI的近似值,它比浮子可以容纳的任何东西都精确得多。
如果你想要更高的精度,你需要找到一个逐个计算数字的算法,并在计算时将它们吐出来。