我正在做另一个C ++练习。我必须从无限系列计算pi的值:
pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 -4 / 11 +。 。
该程序必须在本系列的前1000个术语中的每一个之后打印pi的近似值。 这是我的代码:
#include <iostream>
using namespace std;
int main()
{
double pi=0.0;
int counter=1;
for (int i=1;;i+=2)//infinite loop, should "break" when pi=3.14159
{
double a=4.0;
double b=0.0;
b=a/static_cast<double>(i);
if(counter%2==0)
pi-=b;
else
pi+=b;
if(i%1000==0)//should print pi value after 1000 terms,but it doesn't
cout<<pi<<endl;
if(pi==3.14159)//this if statement doesn't work as well
break;
counter++;
}
return 0;
}
它编译时没有错误和警告,但执行后只显示空的控制台窗口。如果我删除行“if(i%1000 == 0)”,我可以看到它确实运行并打印每个pi值,但它不会停止,这意味着第二个if语句也不起作用。我不知道还能做什么。我假设它可能是一个简单的逻辑错误。
答案 0 :(得分:20)
好吧,我%1000永远不会= 0,因为你的计数器从i = 1开始,然后以2为增量。因此,我总是奇数,永远不会是1000的倍数。
它永远不会终止的原因是算法不会精确地收敛到3.14157 - 它在低于或高于近似时将是更高的精度。你想说“当在3.14157的给定增量内”时,写一下
if (fabs(pi - 3.14157) < 0.001)
break
或类似的东西,但是在你停下来之前想要“接近”。
答案 1 :(得分:7)
因为你从1开始并以2递增,所以我总是一个奇数,所以i%1000永远不会是0。
答案 2 :(得分:4)
你有多个问题:
一个。 i%1000 == 0永远不会是真的,因为你只迭代奇数。
B中。 pi == 3.14159:你不能像那样比较双值,因为表示浮点数的方式(你可以在另一个问题中阅读它)。为了使它起作用,你应该以另一种方式比较这些值 - 一种方法是将它们相互减去并检查绝对结果是否低于0.0000001。
答案 3 :(得分:2)
if(abs(pi - 3.14159) < 0.000005)
。i%1000
永远不会为0,因为i
总是奇数。答案 4 :(得分:2)
不应该是:
if (counter%1000==0)
答案 5 :(得分:2)
我从1开始然后以2递增。因此我总是奇数并且永远不会是1000的倍数,这就是为什么如果(i%1000 == 0)从未通过。
< / LI>由于浮动精度问题,直接比较浮点数不起作用。您需要比较值之间的差异是否足够接近。
答案 6 :(得分:2)
pi = 4 - 4/3 + 4/5 - 4/7 + 4/9 -4/11 + ...
要概括
pi =Σ i = 0 ∞( - 1) i 4 /(2 i +1)
这为我们提供了一个更清晰的方法来解决每个学期; i '的任期由下式给出:
double term = pow(-1,i%2) * 4 / (2*i+1);
其中 i = 0,1,2,...,N
因此,我们的循环可以相当简单,给定一些迭代次数N
int N=2000;
double pi=0;
for(int i=0; i<N; i++)
{
double term = pow(-1,i%2) * 4 / (2*(double)i+1);
pi += term;
cout << i << "\t" << pi <<endl;
}
您的原始问题“该程序必须在本系列的前1000个术语的每一个之后打印pi的近似值”。这并不意味着需要检查是否已达到3.14159,所以我没有在此处包含此内容。 pow(-1,i%2)
调用只是为了避免if
语句(速度很慢),并防止大型 i 出现任何并发症。
请注意,经过多次迭代后,pi的大小与校正项的大小(比如-4/25)之间的差异将会很小,超出{{1}的精度。 ,所以你需要更高精度的类型来处理它。
答案 7 :(得分:0)
默认情况下,abs使用abs的宏来表示int。对于双打,请使用cmath库。
#include <iostream>
#include <cmath>
int main()
{
double pi=0.0;
double a=4.0;
int i = 1;
for (i=1;;i+=2)
{
pi += (1 - 2 * ((i/2)%2)) * a/static_cast<double>(i);
if( std::abs(pi - 3.14159) < 0.000001 )
break;
if (i > 2000) //1k iterations
break;
}
std::cout<<pi<<std::endl;
return 0;
}
答案 8 :(得分:0)
这是更正后的代码。我认为如果有人遇到类似问题,将来可能会有所帮助。
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double pi=0.0;
int counter=1;
for (int i=1;;i+=2)
{
double a=4.0;
double b=0.0;
b=a/static_cast<double>(i);
if(counter%2==0)
pi-=b;
else
pi+=b;
if(counter%1000==0)
cout<<pi<<" "<<counter<<endl;
if (fabs(pi - 3.14159) < 0.000001)
break;
counter++;
}
cout<<pi;
return 0;
}
答案 9 :(得分:0)
这是一个更好的:
class pi_1000
{
public:
double doLeibniz( int i ) // Leibniz famous formula for pi, source: Calculus II :)
{
return ( ( pow( -1, i ) ) * 4 ) / ( ( 2 * i ) + 1 );
}
void piCalc()
{
double pi = 4;
int i;
cout << "\npi calculated each iteration from 1 to 1000\n"; //wording was a bit confusing.
//I wasn't sure which one is the right one: 0-1000 or each 1000th.
for( i = 1; i < 1000; i++ )
{
pi = pi + doLeibniz( i );
cout << fixed << setprecision( 5 ) << pi << "\t" << i + 1 << "\n";
}
pi = 4;
cout << "\npi calculated each 1000th iteration from 1 to 20000\n";
for( i = 1; i < 21000; i++ )
{
pi = pi + doLeibniz( i );
if( ( ( i - 1 ) % 1000 ) == 0 )
cout << fixed << setprecision( 5 ) << pi << "\t" << i - 1 << "\n";
}
}