2


1

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

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

プログラムは、このシリーズの最初の1,000項のそれぞれの後に、概算のpiの値を印刷する必要があります。 これが私のコードです:

#名前空間stdを使用します。

int main(){double pi = 0.0; intカウンタ= 1。

for(int i = 1 ;; i = 2)//無限ループ、pi = 3.14159 {double a = 4.0;}の場合は "中断"する必要があります。二重b = 0.0。

b = a / static_cast(i);

if(counter%2 == 0)pi- = b;そうでなければpi = b。

if(i%1000 == 0)// 1000用語の後に円周率の値を表示しますが、cout <ではありません

エラーや警告なしにコンパイルされますが、実行後は空のコンソールウィンドウのみが表示されます。 行「if(i%1000 == 0)」を削除すると、すべてのpi値が実行されて印刷されることがわかりますが、停止しないため、2番目のifステートメントも機能しません。 他に何をするべきかわからない。 それはおそらく単純な論理的な誤りだと思います。

10 Answer


20


さて、あなたのカウンターはi = 1から2の増分で動くので、i%1000は決して0にはなりません。 したがって、iは常に奇数であり、1000の倍数になることはありません。

それが決して終わらない理由は、アルゴリズムが正確に3.14157に収束しないということです - それは、近似の下または上のどちらかでより高い精度になるでしょう。 「3.14157の特定のデルタ内にあるとき」と言いたいので、次のように書きます。

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

それとも似たようなものですが、「閉じる」には停止する前に取得したいと思います。


7


iを1から始めて2ずつ増分するので、iは常に奇数になるので、i%1000は0にはなりません。


4


複数の問題があります。

  1. i%1000 == 0は、奇数だけを繰り返しているので、決して真実にはなりません。

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


2


  1. 浮動小数点の精度の問題があります。 `if(abs(pi - 3.14159)<0.000005)`を試してください。

  2. 「i」は常に奇数であるため、「i%1000」は0になることはありません。


2


そうではありません:

if(counter%1000 == 0)


2


  1. iは1から始まり、2ずつ増加します。 したがって、iは常に奇数であり、1000の倍数になることはありません。そのため、(i%1000 == 0)が合格することはありません。

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


2


pi = 4 - 4/3 4/5 - 4/7 4/9 -4 / 11 …​

一般化

pi =Σ〜i = 0〜(-1)^ _ i_ ^ 4 /(2i 1)

これにより、各用語に対するより明確なアプローチが得られます。 _i_番目の項は次の式で与えられます。

二重項= pow(-1、i%2)* 4 /(2 * i 1);

i = 0,1,2、…​、N

したがって、繰り返し回数Nを考えると、ループはかなり単純になります。

int N = 2000。二重π= 0。 (int i = 0; iの場合

あなたの最初の質問は、「プログラムは、このシリーズの最初の1000用語のそれぞれの後にpiの近似値を印刷しなければならない」と述べました。 これは3.14159に達したかどうかをチェックする必要がないことを意味するので、ここではこれを含めません。 `pow(-1、i%2)`呼び出しは単に `if`ステートメント(これは遅いです)を避け、大きな_i_を使った複雑さを防ぐためです。

何度か繰り返した後、piの大きさと補正項の大きさ(例えば-4/25)の差は非常に小さくなるので、 `double`の精度を超えることになりますそれを扱うためにより高い精度の型が必要です。


0


デフォルトでは、absはint用のabsマクロを使用します。 倍精度の場合は、cmathライブラリを使用してください。

#include #include

int main(){double pi = 0.0;

二重a = 4.0。 int i = 1;

(i = 1 ;; i = 2){について

pi =(1  -  2 *((i / 2)%2))* a / static_cast(i);

if(std :: abs(pi  -  3.14159)<0.000001)break;

if(i> 2000)// 1k回の反復が中断されます。 }

std :: cout <


0


これが修正されたコードです。 誰かが同様の問題を抱えているならば、私はそれが将来役に立つかもしれないと思いました。

#include #include

名前空間stdを使用する。

int main(){double pi = 0.0; intカウンタ= 1。

(int i = 1 ;; i = 2){double a = 4.0;二重b = 0.0。

b = a / static_cast(i);

if(counter%2 == 0)pi- = b;そうでなければpi = b。

if(counter%1000 == 0)cout <


0


これはより良いものです:

クラスpi_1000 {public:double doLeibniz(int i)//ライプニッツの有名なpiの公式。出典:Calculus II :) {return((pow(-1、i))* 4)/((2 * i)1); }

void piCalc(){double pi = 4; int i;

cout << "\ npiは1から1000までの各反復を計算しました\ n"; //文言は少し混乱しました。 //私はどれが正しいものかわかりませんでした。 (i = 1; i <1000; i){pi = pi doLeibniz(i); cout << fixed << setprecision(5)<< pi << "\ t" << i 1 << "\ n"; }

pi = 4; cout << "\ npiは1000回の繰り返しごとに1から20000を計算しました\ n"; (i = 1; i <21000; i){pi = pi doLeibniz(i); if((((i  -  1)%1000)== 0)cout <<固定<< setprecision(5)<< pi << "\ t" << i  -  1 << "\ n" }

}