2

私は別のC++演習を行っています。無限級数から円周率の値を計算する必要があります。

pi = 4-4/3 + 4/5 – 4/7 + 4/9 -4/11+。。。

プログラムは、このシリーズの最初の1,000項のそれぞれの後に、円周率の近似値を出力する必要があります。これが私のコードです:

#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値が実行および出力されることがわかりますが、停止しません。つまり、2番目のifステートメントも機能しません。他に何をすべきかわかりません。おそらく単純な論理的エラーだと思います。

4

10 に答える 10

20

さて、i%1000は決して= 0になりません。これは、カウンターがi = 1から実行され、その後2ずつ増加するためです。したがって、iは常に奇数であり、1000の倍数になることはありません。

それが決して終了しない理由は、アルゴリズムが正確に3.14157に収束しないためです。これは、近似の過小または過大のいずれかでより高い精度になります。「3.14157の所定のデルタ内にあるとき」と言いたいので、次のように記述します。

if (fabs(pi - 3.14157) < 0.001)
  break

または同様の何か、しかしあなたが停止する前にあなたが取得したい「近い」ために。

于 2009-09-25T20:01:40.657 に答える
7

iを1から開始し、2ずつインクリメントするため、iは常に奇数であるため、i%1000が0になることはありません。

于 2009-09-25T20:00:48.100 に答える
4

複数の問題があります:

A. 奇数のみを繰り返しているため、i%1000==0 が true になることはありません。

B. pi==3.14159 : 浮動小数点数の表現方法が原因で、同じように double 値を比較することはできません (別の質問でここで読むことができます)。それを機能させるには、別の方法で値を比較する必要があります。1 つの方法は、値を互いに減算し、絶対結果が 0.0000001 よりも小さいことを確認することです。

于 2009-09-25T20:08:43.800 に答える
2
  1. 浮動小数点の精度に問題があります。試してみてくださいif(abs(pi - 3.14159) < 0.000005)
  2. i%1000iは常に奇数であるため、0になることはありません。
于 2009-09-25T20:01:45.623 に答える
2

すべきではありません:

if (counter%1000==0)
于 2009-09-25T20:02:52.573 に答える
2
  1. iは1から始まり、2ずつ増加します。したがって、iは常に奇数であり、1000の倍数になることはありません。そのため、if(i%1000 == 0)は決して通過しません。

  2. 浮動小数点の精度の問題により、浮動小数点数を直接比較することはできません。値の差が十分に近いことを比較する必要があります。

于 2009-09-25T20:03:26.347 に答える
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;
}

元の質問には、「プログラムは、このシリーズの最初の 1,000 項のそれぞれの後に、pi のおおよその値を出力する必要がある」と記載されていました。これは、3.14159 に到達したかどうかを確認する必要があることを意味するものではないため、ここには含めません。このpow(-1,i%2)呼び出しは、if(遅い) ステートメントを回避し、大きなiによる複雑さを防ぐためのものです。

何度か繰り返した後、pi の大きさと補正項 (たとえば -4/25) の大きさの差が非常に小さくなり、 a の精度を超えてdoubleしまうので、より高い精度が必要になることに注意してください。対処するタイプです。

于 2009-09-27T17:04:53.310 に答える
0

デフォルトでは、absはint用のabsマクロを使用します。ダブルスの場合は、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;
}
于 2009-09-25T23:50:18.827 に答える
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;
}
于 2009-09-27T13:08:06.673 に答える
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";
    }

}
于 2013-09-28T22:13:26.920 に答える