• ベストアンサー

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

この前、学校の授業でマチンの公式による円周率の計算をするプログラムを以下の方針で考えました。ここで、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

  • 離散フーリエ変換のプログラムについて

    今DFTのプログラムをC言語で書いているんですが、うまく動いてくれません。 DFTの式はX(k)=1/N{Σx(k)*e^(-j2πkn/N)}のシグマの中をn=0からN-1まで足し合わせればいいと思っているのですがちがいますか。 下にプログラムを書きますのでお願いします。 void DFTcore(double x[],int N,double A[],double fai[],double a_rl[],double a_im[]){     x[]はデータ     Nはデータ数     A[]は振幅     fai[]は位相差     a_rl[]は実数部、a_im[]は虚数部 double w,a; int k,n,t; for(k=0;k<N;k++){  //初期化    a_rl[k]=0.0;  //実数部    a_im[k]=0.0;  //虚数部   }     時間間隔は1秒 for(k=0;k<N;k++){       for(n=0;n<N;n++){   w=((2*PI)/N)*k*n;         a_rl[k]=a_rl[k]+x[k]*cos(w);   a_im[k]=-a_im[k]+x[k]*sin(w);  }   a_rl[k]=a_rl[k]/(double)N;実数部   a_im[k]=-a_im[k]/(double)N; 虚数   A[k]=sqrt(a_rl[k]*a_rl[k]+a_im[k]*a_im[k]); //振幅    fai[k]=atan(a_im[k]/a_rl[k]); //位相 } }

  • 台形公式について

    台形公式を使って、2*sqrt(1-x*x)の-1から1の積分の近似値を求めようと思うのですが、結果が違う気がします。おかしなところがありますか?また、皆さんの結果ではどういった結果が出てきますか? 台形公式のプログラムリスト double daikei(double N){ int k; double y,S,sum; sum = 0.0; for(k=0; k<=N; k++){ y = 4.0 * sqrt((k/N)*(1.0+(k/N))); if(k==0 , k==N){ S = (1.0/N) * y; } else { S = (2.0/N) * y; } sum = sum + S; } return sum; }

  • 以下のプログラムを作るとすると・・・・・・?

    プログラム作成の勉強をしているのですが、よく分かりません。お分かりの方、ぜひ教えてください。 log(1+x)=Σ_[M,n=1]{(-1)^(n+1)/n}・x^n M=∞ 上の式から有限なMの値とxの値を入力し、Do loopで第M項までの総和によりlog(1+x)の近似値を求め、組み込み関数logYの値と総和による近似解を求めた値の順でディスプレイ上に書き出すプログラムを作成するにはどうしたらよいでしょうか? どうかよろしくお願いします。(使っているツールはxemacsです。)

  • 関数の積分を求めるプログラムで質問です。

    シンプソンの公式を用いて積分を求めるプログラムで、 「 y=1/(1+x*x) のように±∞で0に収束するような関数は以下のような無限積分を求めることができる。 ∫(-∞→∞){1/(1+x*x)}dx …(a) ただし、無限区間を分割することはできないので、コンピュータを用いた計算では ∫(-a→a){1/(1+x*x)}dx のaに大きな値を入れることで代用する。この積分を求めるプログラムをシンプソンの式を用いて作成し、以下の3ケースについて値を求めて真値と比較せよ。真値は式(a)を解析的に積分することで求めよ。 ・a=100、N=1000 ・a=100、N=500 ・a=200、N=1000 (Nは以下のプログラムと対応しているものです) 」 というもので参考としてS=∫(1→2){1/x}dxをシンプソンの公式を使い求めるものは以下のものなのですが #include <stdio.h> double f(double x) { return 1/x; } int main() { int i,N; double a,b,h,S; double x[1000],y[1000]; a=1.0; b=2.0; N=10; h=(b-a)/N; for(i=0;i<=N;i++) x[i]=a+i*h; y[0]=f(x[0]); y[N]=f(x[N]); S=h*(y[0]+y[N])/3.0; for(i=1;i<=N-1;i=i+2) { y[i]=f(x[i]); S=S+h*y[i]*4.0/3.0; } for(i=2;i<=N-2;i=i+2) { y[i]=f(x[i]); S=S+h*y[i]*2.0/3.0; } printf("N=%d,S=%15.10lf\n",N,S); } これを生かしてプリグラムをつくりたいのですが、分からなくて困っています。助けてください。

  • シンプソン公式

    数学が苦手で、わからないので教えていただきたいのですが。 (1)区間0≦x≦1において関数f(x)=1-x^2を台形公式で近似計算するとき、どんなことがいえるのでしょうか。 (2)区間-1≦x≦1において関数f(x)=|1/4-x^2|をシンプソン公式で計算するとき、どんな方針でやればいいのでしょうか。 以上、よろしくお願いいたします。

  • LU分解を利用した逆行列のプログラム(Java)

    LU分解を利用した逆行列のプログラムが作れません… というか、作ったのですが実行するとエラーが出てしまいます(´Д`;) どこをどう直せばいいか、もしくはこのようにプログラムした方が効率がよい などのアドバイスどなたか下さい double a[][]={{2,5,4}, {2,3,-1}, {6,9,28}}; int N=a.length; double[][] s=new double[N][N]; for(int k=0; k<a[0].length-1; k++){ for(int i=k+1; i<N; i++){ s[i][k]=a[i][k]/a[k][k]; a[i][k]=s[i][k]; for(int j=k+1; j<N; j++){ a[i][j] -= s[i][k] * a[k][j]; } } } double[][] y=new double[N][N]; double[][] X=new double[N][N]; double[][] e=new double[N][N]; for(int i=0;i<N;i++){ for(int j=0;j<N;j++){ if(i==j){ e[i][j]=1; }else{ e[i][j]=0; } } } for(int i=0;i<N;i++){ y[1][i]=e[1][i]; for(int k=2;k<=N;k++){ for(int j=1;j<=N;j++){ y[k][i]=e[k][i]-s[k][j]*y[j][i]; } } X[N][i]=y[N][i]/a[N][N]; for(int k=N-1;k>=1;k--){ for(int j=k+1;j<=N;j++){ X[k][j]=(y[k][j]-s[k][j]*X[j][i])/a[k][k]; } } } for(int i=0;i<N;i++){ for(int j=0;j<N;j++){ System.out.printf(" %6.5f ", X[i][j] ); } System.out.println(""); }

  • 漸化式を用いたπを求めるプログラム

    下のプログラムの問題がわかりません。教えていただけませんか? 半径1の円に内接する正6・2^n角形の1辺の長さをa(n)とし  a(n)+1=a(n)/√2+√4-a^2(n) の式のπの近似値を計算するプログラムを作成しなさい。  ※()の中は添え字です。 あと√2+√4-a^2(n)の文章は √のなかに2+√4-a^2(n)の式が入ってる形です。

  • C言語のプログラムで質問です。

    C言語のプログラムで質問です。 これは、2元1次連立方程式の解を求めるプログラムです。 このプログラムを (1)3元1次連立方程式の解を求めるプログラムにする (2)係数行列、定数行列(6、7行目)をキーボードからの入力にする。 ようにしたいのですが、どうすればよいでしょうか。 前半の部分を変えれば良いようなのですが分かりません。教えてください。 #include <stdio.h> #include <math.h> /* gauss22.c */ #define N 2 main(){ double A[N][N]={1.,4.,3.,2.}, Aa[N][N]; /*簡単のため係数行列を予め指定*/ double b[N]={4.,5.}, x[N], bb[N], e[N]; /*簡単のため定数ベクトルを予め指定*/ int n=2; int i, j, k; double akk, aik, s; /* save original coefficients */ for (i=0; i<n; i++){ for (j=0; j<n; j++){ Aa[i][j]=A[i][j]; } bb[i]=b[i]; } /* forward operation */ for (k=0; k<n-1; k++){ akk=1/A[k][k]; for (i=k+1; i<n; i++){ aik=-A[i][k]*akk; for (j=k+1; j<n; j++){ A[i][j]+=aik*A[k][j]; } b[i]+=aik*b[k]; } for (j=k+1; j<n; j++){ A[k][j]*=akk; } b[k]*=akk; } /* backward operation */ x[n-1]=b[n-1]/A[n-1][n-1]; for (k=n-2; k>=0; k--){ s=0.0; for (j=k+1; j<n; j++){ s+=A[k][j]*x[j]; } x[k]=b[k]-s; } /* chek */ for (i=0; i<n; i++){ s=0.0; for (j=0; j<n; j++){ s+=Aa[i][j]*x[j];} e[i]=s-bb[i]; printf("x(%d)=%f error=%f?n",i, x[i], e[i]); } }

  • C言語のプログラムについて

    下記は、何言語かわからないです。 これをC言語にするにはどうすればよいでしょうか。 プログラムは、「ニュートン法を用いて、方程式x^3(xの3乗)-4=0の近似解を求めるプログラム。ただし、実数解と、近似解の誤差は、0.0001以下とする。ここで、この方程式の導関数は、3x^2(3*xの二乗)である。」 100 DEF F(X)=X*X*X-4 110 DEF G(X)=3*X*X 120 INPUT PROMPT "初期値":A 130 LET B=A-F(A)/G(A) 140 IF ABS(A-B)<=.0001 THEN 170 150 LET A=B 160 GOTO 130 170 PRINT "近似解";B 180 END 以上です。 ご回答よろしくお願いいたします。

  • 数列の問題で質問です。現在、学校では漸化式まで習っています。数学的帰納

    数列の問題で質問です。現在、学校では漸化式まで習っています。数学的帰納法は2学期に習います。 夏休みの宿題で、どうしてもわからないものが1題あります。教えて頂けないでしょうか。 f(x)=(x+1)(x+2)(x+3)……………………(x+n)を展開したときのx^kの係数をak( kは実際は小さい添え字です)とする。 (1)an-1を求めよ。(n-1)は添え字です。 (2)an-2を求めよ。(n-2)は 添え字です。 (3)a0+a1+a2+a3+…………+anを求めよ。 (数字、nは添え字です)