• ベストアンサー

プログラムのおかしいところを教えてください

ライプニッツの公式により、円周率の近似値を求めるプログラムを作 成しなさい。ただし、この公式は収束が遅い。          1     1      1     1     1      1       1    1 円周率=4(── - ── + ── - ── + ── - ──+…- ──+──)          1    3      5      7     9     11      47    49 ってやつをJAVAでやるのですが自分で作ったのは class en{ public static void main(String argv[]) { int i;double n,o,p,q,r; n=0;o=0;p=0;q=0;r=0; for (i=1; i<=49; i=i+4) { n=1/i; o=o+n; } for (i=3; i<=47; i=i+4) { p=1/i; q=q+p; } r=4*(o-q); System.out.println("円周率="+r); } } なんですが 結果が円周率=4.0になってしまいます。アドバイスをお願いします

  • Java
  • 回答数6
  • ありがとう数2

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

  • ベストアンサー
  • takaP-
  • ベストアンサー率79% (83/105)
回答No.4

補足というか訂正です。 >実数と整数を使った計算をする場合は・・・ というのは正しい説明ではなかったです、申し訳無い。 「整数値と整数値を使った計算をする場合」に訂正さ せてもらいます。 n=1/i ; の右辺、1/i はどちらも、整数値です。 よって小数点以下は切り捨てになります。 小数点以下を含む計算を望む場合は、どちらかを 実数値にすればいいので。。。 n=1.0/i ; n=1/(double)i ; のどちらかにすれば良いと思います。

その他の回答 (5)

回答No.6

n=(double)1/(double)i; のようにdouble型を求めるのであればint/intではなくて double/doubleのようにすればOKです。

hige-otoko
質問者

お礼

回答をしてくださったみなさんにこの場を借りてお礼を言わせていただきます。 みなさんありがとうございました double/double型にしたらできました。 やっぱりそこが悪かったみたいですね。 また、わからない事があったらそのときはよろしくお願いします

回答No.5

こんにちは。 つまらないことで支障があるかはわかりませんが、一つ気になったとこがあるので。 double n,0,p,q,r を 0 で初期化しているようですが、0.0 にやるのが一般的です。 こうしないとまずいとか本で書いてあったような気が…たしか。 double型の答えを出すなら double/double という形にしないといけません。 上のやり方だとそれになってないようなので。 例えば上の for の部分を for (double i = 0.0; i < 49.0; i+=4.0) { o += 1.0 / i; } for (i = 3.0; i < 47.0; i+=4.0) { q += 1.0 / i; } とすればいいかと。 間違ってたらごめんなさいね。

  • takaP-
  • ベストアンサー率79% (83/105)
回答No.3

問題は、変数 i にあります。 これをint(整数型)にしてしまうと、 n=1/i; のdouble(実数型)n には右辺 1/i の小数点数 切捨て値が入る事になります。 こういった実数と整数を使った計算をする場合は 整数型の方を実数型へキャストしなければなりま せん → n=1/(double)i ; それか、i を実数型として宣言するかですね。

  • imogasi
  • ベストアンサー率27% (4737/17068)
回答No.2

もっと短くなるのじゃないでしょうか。 VBAでやりましたが、JAVAに置換えました。 Sub test01() Dim p(101) p(1) = 1 For n = 2 To 100 p(n) = p(n - 1) + ((-1) ^ (n - 1)) / (2 * n - 1) Cells(n, 1) = p(n) Next n Cells(n, 1) = 4 * p(n - 1) End Sub 3.131592904になりました。 <Java> class en1{ public static void main(String args[]) { int n; double p[]; p=new double[101]; p[1] = 1; for(n = 2;n<101;n=n+1){ p[n] = p[n - 1] + Math.pow((-1) , (n - 1)) / (2 * n - 1); System.out.println(p[n]); } System.out.println("円周率="+ 4.0 * p[n - 1]); } }

  • taknt
  • ベストアンサー率19% (1556/7783)
回答No.1

プログラムをするときに 陥りやすいのですが、 小数点などで、切捨てられる部分があるということです。 小数点を含む計算は、うまくやらないと実際の計算と合わなくなる場合があります。 上記の例だと多分、小数点以下が 四捨五入されているんじゃないのでしょうか?

hige-otoko
質問者

補足

回答ありがとうございます どこをどうすればいいかも教えていただけるとありがたいのですが・・・

関連するQ&A

  • 次のプログラムは、円周率だの近似値を求めるプログラムである。プログラム

    次のプログラムは、円周率だの近似値を求めるプログラムである。プログラム中の○に適するものを記入しなさい。 これを教えてください! C言語です #include<stdio.h> void main(void) { int sei,en; float pai,x,y,r; r=1.0; sei=0; en=0; for(x=0,1;○;x=x+0,1){ for(y=0.1;y<=1.0;○){ sei=sei+1; if((x*x+y*y)<=r*r)en=○; } } pai=(4.0*○)/(float)sei; printf("円周率=○¥n",pai); }

  • プログラムの違いを教えて下さい・・・

    public class Gold1 { static int prime(int number){ int count=0; for(int i=2; i<number; i+=2){ if(number%i==0) count++; } return count; } public static void main(String[] args) { long start = System.currentTimeMillis(); int n, p; //System.out.println("4=2+2"); for(n=6; n<=100000; n+=2){ for(p=2; p<n; p++){ if(prime(p)==2 && prime(n-p)==2){ //System.out.println(n + "=" + p + "+" + (n-p)); break; } } if(p==n){ //System.out.println("この予想は間違いと判明!"); break; } if(n%1000==0){ long stop = System.currentTimeMillis(); System.out.println(n + " " + (stop-start)); } } } } ---------------------------------------------------------------- この上のプログラムの一部を ---------------------------------------------------------------- if(prime(p)==0 && prime(n-p)==0){ //System.out.println(n + "=" + p + "+" + (n-p)); break; } ---------------------------------------------------------------- というふうに変えたらどういう意味があるのですか??

    • ベストアンサー
    • Java
  • 円周率が定数であることの証明

    円周率πが3.14...と半径によらず一定であることの証明って、どうすればよいのでしょうか。 定義は π=【円周の長さ】/【直径(2r)】 ですよね。 直径が既知だとそて、円周の長さも求めなくてはならないとき、半径rの円とその円に内接する正n角形(周長=Ln)を考えた際に、 円周の長さが【lim(n→∞)Ln】で近似されることも前段階として示す必要がある気がします。 つまり、 (ⅰ) lim(n→∞)Lnが存在すること(=収束すること?) (ⅱ) lim(n→∞)Lnが円周の長さとして適当か。 ってことなんですけど・・・。 (ⅰ)も(ⅱ)も感覚的には収束すると思うし、適当だと思うんですけどうまく証明ができません。 最終的にはπが定数であることの証明がしたいのですが、その前段階のことも気になりました。 どなたか教えてください。お願いします。

  • プログラムの意味がわからなくて困っています

    こんにちは。以下のプログラムの意味がわからなくて困っています。分数q/p(p、qはともに正の整数)に関係するもので、3/13を入力したときの出力と、配列R()がどんな変化をしていくかを教えてください。 100 option base 0 110 dim A(1000) 120 dim R(999) 130 let N=1000 140 for I=0 to N-1 150 let R(I)=0 160 Next I 170 do 180 print"分母p="; 190 input P 200 if (P>N) then 210 print"分母は1000以下にしてください” 220 end if 230 loop while(P>N) 240 print"分子q="; 250 input Q 260 let A(0)=int(Q/P) 270 let Q=mod(Q,P) 280 let K=0 290 Do 300 let K=K+1 310 let R(Q)=K 320 let Q=Q*10 330 let A(K)=int(Q/P) 340 let Q=mod(Q,P) 350 loop while (R(Q)=0) 360 print A(0);"."; 370 for I=1 to R(Q)-1 380 print A(I); 390 next I 400 if (R(Q)<K) or (A(K)<>0) then 410 print "{"; 420 for I=R(Q) to K 430 print A(I); 440 next I 450 print"}"; 460 end if 470 end 100から160までで配列Aを1000個、配列Rを999個準備し、配列Rの中身を0にしている。 170から230で分母Pに13を入れ分母が1000以下になることを確認している。1000以上であれば、1000以下になるまでループ内を繰り返す。 240以下で分子を入れているようですが、ここからよくわからなくなってしまいました。 よろしくお願いします。  

  • もし良ければ見て下さい

     例えば、「in」を入力すれば、食わせたファイル内の「in」を含む行を全て出力するプログラムを作りました。  しかし、  (1)このファイル自身を食わせて「*」を入れると関係ない行まで出力される。  (2)このファイル自身を食わせて「re」を打つと空白の行しか出力されない    (どうして「return(0); 」が出力されない?) のです。  もし良ければこのプログラムを見て、ご指摘ください。 #include<stdio.h> int main(int argc,char **argv) { FILE *file1; int i,nagasa; char line[256],*p,*q,*r; file1=fopen(argv[1],"r"); for(p=argv[2],nagasa=0;*p;++p,++nagasa); while(fgets(line,256,file1)!=NULL) { for(p=line,i=0;*p!='\0';++p) { for(q=argv[2];*q;++q) { while(*p!=*q && *p!='\0')++p; if(*p!='\0' && *q!='\0') { for (i=0;*q==*p;++p,++q,++i); } } } if(i==nagasa) for(p=line;*p!='\0';++p) printf("%c",*p); } return(0); }

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

    C言語のプログラムで質問です。 ヤコビ法で固有値・固有ベクトル絵を求めたいのですが、固有値は上手く出るのですが、 固有ベクトルがめちゃくちゃな値が出ます。何が間違っているのでしょうか教えてください。下のは一応自分で作ってみたプログラムです。 #include <stdio.h> #include <math.h> #define N 4 #define PI 3.14159 void jacobi(double a[N][N], double λ[N], double v[N][N]); int main(void) { int i, j; double a[N][N], λ[N], v[N][N], x; for(i=0;i<N;i++){ printf("\n a[%d][0] a[%d][1] a[%d][2] a[%d][3]=",i,i,i,i); scanf("%lf %lf %lf %lf",&a[i][0],&a[i][1],&a[i][2],&a[i][3]); } jacobi(a, λ, v); for(j=0; j<N; j++){ printf("\n固有値λ[%d]=%lf", j, λ[j]); printf("\n固有ベクトル\n"); for(i=0; i<N; i++){ printf("%lf\n", v[i][j]); } } return 0; } /* ヤコビ法による固有値計算 */ void jacobi(double a[N][N], double λ[N], double v[N][N]) { int i, j, kmax=100, repeat, p, q; double eps, c, s,theta, gmax; double apq, app, aqq, apqmax, apj, aqj, vip, viq; gmax=0.0; for(i=0; i<N; i++){ s=0.0; for(j=i+1; j<N; j++){ s += fabs(a[i][j]); } if(s>gmax) gmax=s; } eps=0.000001*gmax; for(i=0; i<N; i++){ for(j=0; j<N; j++){ v[i][j]=0.0; } v[i][i]=1.0; } for(repeat=1; repeat<kmax; repeat++){ /* 収束判定 */ apqmax = 0.0; for(p=0; p<N; p++){ for(q=0; q<N; q++){ if(p!=q){ apq=fabs(a[p][q]); if(apq>apqmax) apqmax=apq; } } } if(apqmax<eps) break; for(p=0; p<N-1; p++){ for(q=p+1; q<N; q++){ apq=a[p][q]; app=a[p][p]; aqq=a[q][q]; if(fabs(apqmax)<eps) break; /*回転角計算*/ if(fabs(app-aqq)>=1.0e-15){ theta= 0.5*atan(2.0*apq/(app-aqq)); }else{ theta= PI/4.0; } c = cos(theta); s = sin(theta); a[p][p] = app*c*c + 2.0*apq*c*s + aqq*s*s; a[q][q] = app*s*s - 2.0*apq*c*s + aqq*c*c; a[p][q] = 0.0; a[q][p] = 0.0; for(j=0; j<N; j++){ if(j!=p && j!=q){ apj = a[p][j]; aqj = a[q][j]; a[p][j] = apj*c + aqj*s; a[q][j] = -apj*s + aqj*c; a[j][p] = a[p][j]; a[j][q] = a[q][j]; } } /*固有ベクトル*/ for(i=0; i<N; i++){ v[i][p] = v[i][p]*c+v[i][q]*s; v[i][q] = -v[i][p]*s+v[i][q]*c; } } } eps=eps*1.05; } for(i=0; i<N; i++) λ[i] = a[i][i]; }

  • ゴールドバッハの予想についてのプログラムなんですが・・・

     ゴールドバッハの予想(4以上の任意の偶数は,2つの素数の和で表せる)を表すJavaプログラムです。 ---------------------------------------------------------------- public class Gold { static int prime(int number){ int count=0; for(int i=1; i<=number; i+=2){ if(number%i==0) count++; } return count; } public static void main(String[] args) { long start = System.currentTimeMillis(); int n, p; //System.out.println("4=2+2"); for(n=6; n<100000; n+=2){ for(p=2; p<n; p++){ if(prime(p)==2 && prime(n-p)==2){ //System.out.println(n + "=" + p + "+" + (n-p)); break; } } if(p==n){ //System.out.println("この予想は間違いと判明!"); break; } if(n%1000==0){ long stop = System.currentTimeMillis(); System.out.println(n + " " + (stop-start)); } } } } ---------------------------------------------------------------- 『for(int i=1; i<=number; i++){ のループ、number まで回しているのが無駄である。素数判定は 2 以上、√number 以下の整数で割り切れれば素数でないのでループの上限は√number で良い。number まで回す必要はなく、i で割り切れた時点で prime=1 として 飛び出せばよい。ループを回り終わっても割り切れていなければ prime=2 で出る。』というコメントを、上に書いたプログラムを変更して表すにはどうしたら良いのですか?? 誰か教えて下さい(*_*) お願いします★

    • ベストアンサー
    • Java
  • 図形の面積

    右図のように一辺が16cmの正方形ABCDがあり、 この正方形の各頂点から4cmの場所に点P,Q.R,Sが あります。   この4つの点P,Q,R,Sを通る円oの面積は何平方cmですか。   ただし,円周率はπとします。 このような問題に取り組んでるのですが 半径×半径×πの公式をつかうのでしょうか? 解き方がわかりません。どなたか説明できる方がいましたらよろしくお願いします。

  • マージソートのプログラム

    ↓が自分の作ったマージソートのプログラムなのですが、コンパイルするとエラーが起きてしまいます。 mergesort()にポインタを引数として渡してる、引数の数が足りない、ということが書いてありますが…。 ちゃんとint型を渡してるし、引数の数も合ってるように思います。 どこがおかしいのでしょう? #include<stdio.h> #include<stdlib.h> #include<time.h> #define Max 255 int A[Max]; main(){ int n,k; n=inputdata(); int w=1; mergesort(w,n); printdata(n); return(0); } inputdata(){ //配列に乱数を要素として入れていく int n,i; printf("n= "); scanf("%d",&n); //使用者にいくつの要素を入れるか指定してもらう srand(time(NULL)); for(i=1; i<=n; i++){ A[i]=1+rand()%30; } printf("A[%d]={%d,",n,A[1]); for(i=2;i<n;i++) printf("%d,",A[i]); printf("%d}\n",A[n]); return(n); } void mergesort(int p, int r){ int q; if(p<r){ q=(p+r)/2; mergesort(p,q); mergesort(q+1,r); merge(p,q,r); } } void merge(int p, int q, int r){ int i,j,k,B[Max]; i=p; j=q+1; for(k=p;k<=r;k++){ if((j>r) || ((i<=q)&&(A[i]<=A[j]))){ B[k]=A[i]; i++; }else{ B[k]=A[j]; j++; } } for(k=p; k<=r; k++) A[k]=B[k]; } printdata(int n){ int i; printf("A[%d]={%d,",n,A[1]); for(i=2; i<n; i++) printf("%d,",A[i]); printf("%d}\n",A[n]); } ・エラーメッセージ merge1.c: In function ‘main’: merge1.c:12: warning: passing argument 1 of ‘mergesort’ makes pointer from integer without a cast merge1.c:12: error: too few arguments to function ‘mergesort’ merge1.c: At top level: merge1.c:31: error: conflicting types for ‘mergesort’ /usr/include/stdlib.h:294: error: previous declaration of ‘mergesort’ was here merge1.c:41: warning: conflicting types for ‘merge’ merge1.c:37: warning: previous implicit declaration of ‘merge’ was here

  • javaの簡単な質問です

    学校の課題で、ループ文を使い、1-6までのカードを順に引いた場合、起こりうるパターンを全て表示するプログラムを作りなさいというのが出ました。 六枚全てを引くのだけではなく、一枚や二枚、五枚だけ引くというのもあるので、720+360+120+30+6通りがあります 下が作ったものなのですが、うまくいきません。 こういった場合、どのようなコードを書けばよいのでしょうか?for文で実現可能なのでしょうか?whileで同じ数字が出なくなるまで++するような形にするほうが良いのでしょうか? プログラミング初心者で、よくわかっていないです。すみません。どなたか助けてください。 *printsは表示処理を行う関数です public static void main(String[] args){ int[] numbers=new int[6];; for(int i=0;i<numbers.length;i++){//1 for(int j=0;j<numbers.length-1;j++){//2 int o=(i+j+1)%6; prints(numbers[i],numbers[o]); for(int k=0;k<numbers.length-2;k++){//3 int p=(o+k+1)%6; prints(numbers[i],numbers[o],numbers[p]); for(int l=0;l<numbers.length-3;l++){//4 int q=(p+l+1)%6; prints(numbers[i],numbers[o],numbers[p],numbers[q]); for(int m=0;m<numbers.length-4;m++){//5 int r=(q+m+1)%6; prints(numbers[i],numbers[o],numbers[p],numbers[q],numbers[r]); for(int n=0;n<numbers.length-5;n++){//6 int s=(r+n+1)%6; prints(numbers[i],numbers[o],numbers[p],numbers[q],numbers[r],numbers[s]); } } } } } } private void prints(int... num){ for(int i=0;i<num.length;i++){ System.out.print(num[i]); } } }