• ベストアンサー

マチンの公式による円周率のプログラム

この前、学校の授業でマチンの公式による円周率の計算をするプログラムを以下の方針で考えました。ここで、atanを求めるユーザー定義関数を作りたいのですが、途中までは考えたのですが以下の空欄の部分が、よく分かりません。 【方針】1.数列a(k)=±(1/2k-1)*x^(2k-1)(k=1,2,…)の漸化式を作る。(a(k)のkは添え字です) 2.a(1)+a(2)+a(3)+…+a(N)の値をatan(x)の近似値とする。 (1,2,3,…,Nは添え字です) (プログラムの一部)→atanの近似値を求める関数 double Atan(double x) { double s=_,a=_,kk; int k; //添え字用 for(k=1;k<=x;k++) {s_; //多分式が入る。 kk=(double)k; a_; //多分式が入る。 } return s; } 下線部に適当な文字や式を入れて、この関数を完成させてください。(ヒントをください) ※できれば、このプログラムの形は変えないで、下線部のみを埋めてください。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

グレゴリ級数 Σ[n=0,∞]((-1)^n / (2n + 1)) * x^(2n + 1) グレゴリ級数をN項まで展開する場合、n=0~N-1になります。 Σ[n=0,N-1]((-1)^n / (2n + 1)) * x^(2n + 1) 問題と成っている関数の下線を埋めてもプログラムは完成しません。 根本的に間違えがあります。 グレゴリ級数を素直に書いた場合。 double MyAtan(double x) {  double s = (1)___;  int n;  for (n = 0; n < N; n ++) {   s (2)___  }  return s; } と言う形状が一般的です。 Σは総和です。 Σ[n=0,N-1]((-1)^n / (2n + 1)) * x^(2n + 1) の場合、 > for (n = 0; n < N; n ++) { の様に0~N未満までループさせます。 この時の各nで式「((-1)^n / (2n + 1)) * x^(2n + 1)」を計算し全てを加算したのが総和です。 よって、(2)の下線には式「((-1)^n / (2n + 1)) * x^(2n + 1)」が入る事になります。 「s = s + 加算式」or 「s += 加算式」 また、Σ[n=0,N-1]の初項(n=0)は0.0に対してn=0時の数値を加算したものと考えられます。 よって、(1)には0.0が入ります。 double MyAtan(double x) {  double s = 0.0;  int n;  for (n = 0; n < N; n ++) {   s += 式  }  return s; } 式には「((-1)^n / (2n + 1)) * x^(2n + 1)」が入ります。 乗数はpow関数を使用します。 ・テクニックとして 初項がxと分かっているので double MyAtan(double x) {  double s = x; <-- 初項(n=0)分が計算済み  int n;  for (n = 1; n < N; n ++) { <-- n = 1と成っている   s += 式  }  return s; } とすると複雑な計算の回数が1回減り、少し速くなります。 この関数を大量に実行しない限り、測定誤差の範囲ですが。 また、「(-1)^n 」の部分も条件文にし、powを使わない方が速くなります。 まずは素直に作ってみるのが良いでしょう。

hyper1234
質問者

お礼

ありがとうございます。 皆さんのアドバイスのおかげで、何とか課題を完成することが出来ました!! もしかしたら、また、別の問題で分からない所が出てくるかもしれません。 そのときは是非ともよろしくお願いいたします。

その他の回答 (3)

回答No.3

円周率のプログラムとか懐かしい^^ 何か間違えてないですか? 使用するのグレゴリ級数じゃないのかな? この数列±あるし、課題をもう一度確認した方が良いと思います。 グレゴリ級数って Σ[n=0,∞]((-1)^n / (2n + 1)) * x^(2n + 1) です。 数列で書きたかったら a(1) = x a(2) = x - (1 / 3) * x^3 a(3) = x - (1 / 3) * x^3 + (1 / 5) * x^5 a(4) = x - (1 / 3) * x^3 + (1 / 5) * x^5 - (1 / 7) * x^7 この数列を漸化式にすると a(n+1) = a(n) + ((-1)^n / (2n + 1)) * x^(2n + 1) a(1) = x 普通にΣをループでぶん回せば良いだけかと。

hyper1234
質問者

補足

すみません。 間違えていました! 同じ課題の中にマチンの公式の紹介もしてあったので、勘違いをしていました。 もらったヒントを参考にもう一度考えてみたのですが、まだよく分かりません。 ループの部分を中心にもう少し詳しく教えてください。 (下線部にどんなものが入るのかなど・・・) よろしくお願いします!

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.2

> 変数sは、atanの値を入れる > aは、forループで、方針のa(1),a(2),a(3),…,a(N)の値を順番に計算 なるほど。とすると、 > s_; //多分式が入る。 > kk=(double)k; > a_; //多分式が入る。 ここの計算順番おかしくないですか? 「kk(kの値)」から、「a」を計算して、「s」に加算して行くのでは? > kk=(double)k; > a_; //多分式が入る。 > s_; //多分式が入る。 こういう順番に実行する必要があるのでは? で、「a」は、 > a(k)=±(1/2k-1)*x^(2k-1) を計算して、 「s」は、それを順に足しこんでいけばよさそうですけど・・・ > forループについてですが、これは、a(1),a(2),…の値を > k=1からx(方針ではN)まで計算するために って事ですが・・・ > 2.a(1)+a(2)+a(3)+…+a(N)の値をatan(x)の近似値とする。 つまり「atan(x)=a(1)+a(2)+a(3)+…+a(N)」で、精度(つまりループ回数)を決める「N」と、 個々の「a(k)」を計算するための「x」は、全く別物ですよね? ループを「k=1からx」として大丈夫なんですか? #例えば「Atan(0.576996400392873)」(答えは0.523333333333333ラジアン=30度)を求めようとした場合、 #「x=0.576996400392873」で、1より小さいので、全くループしないことに・・・ 別に「N」を設定しなければ成らないって事ですよね? #Nを、どうやって渡すか(引数で渡すとか、constで固定値にするか)は #方針によるでしょうけど・・・

hyper1234
質問者

お礼

ありがとうございます。 皆さんのアドバイスのおかげで、何とか課題を完成することが出来ました!! もしかしたら、また、別の問題で分からない所が出てくるかもしれません。 そのときは是非ともよろしくお願いいたします。

  • dsuekichi
  • ベストアンサー率64% (171/265)
回答No.1

> マチンの公式 は、ざっと調べただけで詳しくないので、「一般論」で申し訳ありません。 > 途中までは考えたのですが以下の空欄の部分が、よく分かりません。 どういう風に考えたんです? 途中まででよいでは、どう考えたか説明してもらえませんか? 特に、変数「s」や「a」には、何に使う(何の値を格納する)つもりで宣言したのでしょう? 後・・・ > for(k=1;k<=x;k++) これ、間違ってると思うんですけど・・・ どうして(どういう考えで)、こういう式になったんでしょう?

hyper1234
質問者

補足

変数sは、atanの値を入れるために宣言しました。 また、aは、forループで、方針のa(1),a(2),a(3),…,a(N)の値を順番に計算するために宣言したものです。 forループについてですが、これは、a(1),a(2),…の値をk=1からx(方針ではN)まで計算するために、このようにしました(a(k)の値を求めるため)。違うような気がしてはいたのですがそのことをコメントしておくのを忘れました。そこも含め、何を入れたらよいのか分かりません。 残りの部分についてですが、「kk=(double)k」については、もとから、このようにヒントが書いてあったため、そのまま用いました。また、最後の「return s」は計算したatanの値をsとして返すということです。

関連するQ&A

専門家に質問してみよう