为什么在 C++ 中实现高斯勒让德算法没有产生结果?
why this implementation of a Gauss Legendre algorithm in c++ is not producing result?
我正在学习 C++,我在维基百科上找到了高斯-勒让德算法来近似 pi(link: https://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm)。
我试图用 C++ 实现它,但它没有产生任何结果。
这是代码:
#include <iostream.h>
#include <conio.h>
#include <math.h>
#include <iomanip.h>
int main()
{
clrscr();
long double a0 = 1,
b0 = 1 / sqrt(2),
t0 = 1 / 4,
p0 = 1,
an, bn, pn, tn;
int i = 0;
while(i < 3)
{
an = (a0 + b0) / 2;
bn = sqrt(a0 * b0);
tn = t0 - (p0 * (pow((a0 - an), 2)));
pn = 2 * p0;
a0 = an;
b0 = bn;
t0 = tn;
p0 = pn;
}
long double pi = (pow((an + bn), 2)) / (4 * tn);
cout<<pi;
getch();
return 0;
}
当我寻求帮助时,我找到了这个,但在我看来它是一个不同的算法 -
gauss-legendre in c++
更新: 添加 i
增量程序后给出错误结果。
您没有在 while
循环中递增 i
。
编辑:
1. 添加行 i++;
2. 更改此代码--
while(i < 3)
{
an = (a0 + b0) / 2;
bn = sqrt(a0 * b0);
tn = t0 - (p0 * (pow((a0 - an), 2)));
pn = 2 * p0;
a0 = an;
b0 = bn;
t0 = tn;
p0 = pn;
}
--到
while(i < 3)
{
an = (a0 + b0) / 2;
bn = sqrt(a0 * b0);
pn = 2 * p0;
tn = t0 - (p0 * (pow((a0 - an), 2)));
a0 = an;
b0 = bn;
t0 = tn;
p0 = pn;
i++;
}
将 pn 放在 tn 之上。
除了您的 while 循环变量没有更新这一事实,您还错误地声明了您的双打。声明双精度值(例如“1/4”)时,如果您懒惰,最好将它们写为“1.0/4.0”或“1/4.0”。
原因是C/C++会对整数执行“/”运算符,并在事后执行类型转换。本质上你的 t0 = 0(你可以自己检查)。
这是您的代码,经过一些修改以在每次 while 循环迭代时打印完整的双精度。
#include <iostream>
#include <cmath>
#include <limits>
int main()
{
long double a0=1.0, b0 = 1/sqrt(2),
t0 = 1.0/4.0, p0 = 1.0;
long double an,bn,pn,tn;
int i = 0;
long double pi;
typedef std::numeric_limits<double> dbl;
std::cout.precision(dbl::max_digits10);
while(i < 4)
{
an = (a0 + b0)/2.0;
bn = sqrt(a0 * b0);
tn = t0 - (p0 * (a0-an)*(a0-an));
pn = 2*p0;
a0 = an,b0 = bn,p0 = pn,t0 = tn;
pi = (an+bn)*(an+bn) / (4*tn);
std::cout << pi << std::endl;
i++;
}
return 0;
}
我正在学习 C++,我在维基百科上找到了高斯-勒让德算法来近似 pi(link: https://en.wikipedia.org/wiki/Gauss%E2%80%93Legendre_algorithm)。 我试图用 C++ 实现它,但它没有产生任何结果。 这是代码:
#include <iostream.h>
#include <conio.h>
#include <math.h>
#include <iomanip.h>
int main()
{
clrscr();
long double a0 = 1,
b0 = 1 / sqrt(2),
t0 = 1 / 4,
p0 = 1,
an, bn, pn, tn;
int i = 0;
while(i < 3)
{
an = (a0 + b0) / 2;
bn = sqrt(a0 * b0);
tn = t0 - (p0 * (pow((a0 - an), 2)));
pn = 2 * p0;
a0 = an;
b0 = bn;
t0 = tn;
p0 = pn;
}
long double pi = (pow((an + bn), 2)) / (4 * tn);
cout<<pi;
getch();
return 0;
}
当我寻求帮助时,我找到了这个,但在我看来它是一个不同的算法 - gauss-legendre in c++
更新: 添加 i
增量程序后给出错误结果。
您没有在 while
循环中递增 i
。
编辑: 1. 添加行 i++; 2. 更改此代码--
while(i < 3)
{
an = (a0 + b0) / 2;
bn = sqrt(a0 * b0);
tn = t0 - (p0 * (pow((a0 - an), 2)));
pn = 2 * p0;
a0 = an;
b0 = bn;
t0 = tn;
p0 = pn;
}
--到
while(i < 3)
{
an = (a0 + b0) / 2;
bn = sqrt(a0 * b0);
pn = 2 * p0;
tn = t0 - (p0 * (pow((a0 - an), 2)));
a0 = an;
b0 = bn;
t0 = tn;
p0 = pn;
i++;
}
将 pn 放在 tn 之上。
除了您的 while 循环变量没有更新这一事实,您还错误地声明了您的双打。声明双精度值(例如“1/4”)时,如果您懒惰,最好将它们写为“1.0/4.0”或“1/4.0”。
原因是C/C++会对整数执行“/”运算符,并在事后执行类型转换。本质上你的 t0 = 0(你可以自己检查)。
这是您的代码,经过一些修改以在每次 while 循环迭代时打印完整的双精度。
#include <iostream>
#include <cmath>
#include <limits>
int main()
{
long double a0=1.0, b0 = 1/sqrt(2),
t0 = 1.0/4.0, p0 = 1.0;
long double an,bn,pn,tn;
int i = 0;
long double pi;
typedef std::numeric_limits<double> dbl;
std::cout.precision(dbl::max_digits10);
while(i < 4)
{
an = (a0 + b0)/2.0;
bn = sqrt(a0 * b0);
tn = t0 - (p0 * (a0-an)*(a0-an));
pn = 2*p0;
a0 = an,b0 = bn,p0 = pn,t0 = tn;
pi = (an+bn)*(an+bn) / (4*tn);
std::cout << pi << std::endl;
i++;
}
return 0;
}