Cプログラミングで正規乱数を発生させる方法

このQ&Aのポイント
  • Cプログラミングで正規乱数を発生させたいのですが、どこがおかしいのでしょうか?
  • Cプログラム内のファイル操作に関するエラーが発生しているのかもしれません。
  • 正規乱数生成の数式が正しく実装されていない可能性があります。
回答を見る
  • ベストアンサー

Cプログラミングの質問なのですが,

Cプログラミングの質問なのですが, 以下のプログラムで正規乱数を発生させたいのですが,どこがおかしいのでしょうか? fp1のransuuはきちんとtxtで作成されています。 至急お助けください。 #include <stdio.h> #include<stdlib.h> #include<math.h> #define PI 3.141592653589793238 int main (void) { FILE *fp1,*fp2; int i,n; unsigned int x1,x2; double y1,y2; fp1=fopen("ransu.txt","r"); fp2=fopen("seikiransu.txt","w"); for(i=0;i<n;i++) { fscanf(fp1,"%lf",&x1); fscanf(fp1,"%lf",&x2); y1=sqrt(2)*sqrt(-2*log(x1))*cos(2*PI*x2); fprintf(fp2,"%lf\n",y1); } fclose(fp1); fclose(fp2); return 0; }

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

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

>for(i=0;i<n;i++)  まず、前回答者さんも御指摘ですが、変数nが初期化されていませので無限ループかメモリ破壊  を起こす可能性が有ります。 >fscanf(fp1,"%lf",&x1);  fですのでDoubleに変換しますので、x1もx2も破壊されます。  倍精度浮動小数点ですのでスタック上の変数が破壊されます。  CPUによって異なりますが、8バイト以上だと思いますので  スタックを壊して変換します。  従いましてDouble x1、x2宣言が良いのでは? >y1=sqrt(2)*sqrt(-2*log(x1))*cos(2*PI*x2);  ここでもcastしないと桁落ちするかも。 >fprintf(fp2,"%lf\n",y1);  このfの前は”いち”ですか?”エル”ですか?  ”エル”なら”%lf”でDoubleでokですが、”いち”なら  1桁だけの表示になります。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

なんで x1 や x2 を unsigned int にしたの? Box-Muller 法は完全に理解できている?

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.4

「エラーがある」だけではなく「どんなエラーが」「どこで」出るかも書きましょう。 コンパイルエラーならエラーメッセージ本体と出ている行、実行時エラーならデバッガなどで出る箇所を特定しておくと回答側も追跡がかなり楽になります。 今のコードですぐに気付く分としては、nが不定値(初期化されていない)なので何回forが回るかは全く未定義です。 nをx1, x2の数で初期化すれば動作すると思いますが、そもそも読み終わり判定ならfeof()とwhileの組み合わせの方が確実です。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

なんというか, Box-Muller 法をいろいろと勘違いしているように見える. 求める正規乱数の平均と分散はそれぞれどのような値にしたい?

gun0926
質問者

お礼

平均0、分散2にしたいです

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.2

#1でも言われてますが、scanf系の%lfはdoubleに対応しますがx1, x2の型はunsigned intになっていて不整合が起きています。 また、sizeof(double) > sizeof(unsigned int)の環境下では正しく値が取れないのみならず、メモリ破壊により予期せぬバグの原因となるかsegmentation faultの原因になります。 x1, x2の型が正しいのならunsigned intに対応する%uで取らなければならないし、型が間違っているのなら正しくdoubleで宣言しなければなりません。

gun0926
質問者

お礼

ありがとうございます。 #include <stdio.h> #include<stdlib.h> #include<math.h> #define PI 3.141592653589793238 int main (void) { FILE *fp1,*fp2; int i,n; unsigned int x1,x2; double y1,y2; fp1=fopen("ransu.txt","r"); fp2=fopen("seikiransu.txt","w"); for(i=0;i<n;i++) { fscanf(fp1,"%u",&x1); fscanf(fp1,"%u",&x2); y1=sqrt(2)*sqrt(-2*log(x1))*cos(2*PI*x2); fprintf(fp2,"%lf\n",y1); } fclose(fp1); fclose(fp2); return 0; } 上記のように変更したところまだエラーがあるようです。 ほかになにが問題点はあるのでしょうか?

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>unsigned int x1,x2; >fscanf(fp1,"%lf",&x1); >fscanf(fp1,"%lf",&x2); 型が合っていないように見えますが?

関連するQ&A

  • C言語 所々の意味を教えてください><;

    #include <stdio.h> #define N 100 int main(void) { double xn[N], yn[N], x, y; int i, cnt; FILE *fp; if((fp=fopen("data.txt", "r"))==NULL) return 0; for(i=0; fscanf(fp, "%lf%lf", xn + i, yn + i)==2; i++); cnt = i; scanf("%lf", &x); if(x < xn[0] || xn[cnt-1] <= x) return 0; for(i=0; xn[i] < x; i++); y = (yn[i+1] - yn[i]) * (x - xn[i]) / (xn[i+1] - xn[i]) + yn[i]; printf("y = %f\n", y); return 0; } この文の FILE *fp; if((fp=fopen("data.txt", "r"))==NULL) return 0; for(i=0; fscanf(fp, "%lf%lf", xn + i, yn + i)==2; i++); cnt = i; ここの部分でデータテキストを読み込んでるのはわかるんですが fscanf(fp, "%lf%lf", xn + i, yn + i)部分で何をやってるかわかりません。誰か教えてください

  • c言語のファイル出力について

    現在C言語の課題に取り組んでおり、ファイルの中身通りに出力させたいのですが 「ファイルの中身」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 「出力結果」 2022/11/14 16:19:56 4+4,8.000000 2022/11/14 16:20:14 7+7,14.000000 2022/11/14 16:20:18 8+8,16.000000 こういう形で改行されて出てきてしまいます。 どなたか修正点を教えて頂けないでしょうか? #include <stdio.h> #include <string.h> #include <stdlib.h> int main() { int r,i,n; FILE* fp; char sin[9][1000]; fp = fopen("log.txt", "r"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } for (i = 0; i < 9; i++) { fscanf(fp, "%s", &(sin[i])); } fclose(fp); for (i = 0; i < 9; i++) { printf("%s\n", sin[i]); } return 0; }

  • C言語のプログラムを見てください

    ある100行の値がx列、y列の2列あるファイルを読み込んでそれを配列に入れ、yの最小値及びそれと同じ行にあるxの値を表示するプログラムを書きたいのですがy列の最小値を表示するプログラムを書き終えた所でコンパイルして実行してみると正しく値が表示されませんでした。それどころか実行するたびに値が変わってしまいます。どこがおかしいのかわからないため、ご指摘のほどよろしくお願いします。また、できれば同じ行にあるx列の値も表示させるプログラムを教えてください。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #define N 100 int main(void) { int x[N],i; double y[N],min; FILE *fp; fp=fopen("book.dat","r"); if(fp==NULL){ puts("can't open file!"); exit(-1); } for(i=0;i<N;i++){ fscanf(fp,"%d %lf", &x[N],&y[N]); printf("x=%d\n y=%lf\n",x[N],y[N]); } min=y[0]; for(i=1;i<N;i++){ if(y[i]<min) min=y[i]; } fclose(fp); printf("最小値:%lf\n",min); return 0; }

  • cプログラミングについて

    以下はsample.txtというファイルを読み込み、辞書順に並べるプログラミングですが、どう正しく 直したらよいかわかりません。間違っている場所を指摘していただけたらと思います。 (間違えだらけで申し訳ありません) #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXLINE 500 void mysort(char *word[MAXLINE]) { int i,j; char *tmp; for(i=0;;i++){ for(j=i+1;; j++){ if(strcmp(word[j],word[i])==1){ tmp=word[i]; word[i]=word[j]; word[j]=tmp; } } } } int main(void) { int i; FILE *fp; char str[MAXLINE]; fp= fopen("sample.txt", "r"); if (fp == NULL) { printf("fopen error\n"); exit(1); } while(( fgets( str, MAXLINE, fp )) != NULL) mysort(str); for(i=0;; i++) printf("%s\n", str[i]); return 0; }

  • C言語でファイルから読み込みができません。

    以下のプログラムを実行すると よくわからない値が返ってきます。 なぜでしょうか?教えてください。 #include <stdio.h> void main () { FILE *fp; double a, b; int count=0; fp = fopen("test.xls", "r"); while(1) { fscanf(fp, "%lf %lf\n", &a, &b); printf("%f, %f\n", a, b); count++; if(count==10)break; } fclose(fp); } test.xlsの中身は 1.0 2.0 3.0 4.0 5.0 6.0   :   :   :   : です。 よろしくお願いします。

  • C言語について質問です。

    ソートについて勉強していて、乱数列の要素数Nの値を変えていきバブルソートの交換回数、比較回数を数えるプログラムを作り、後は処理時間について調べたいのですが、処理時間を出力するのはどうやってやるのですか?教えてください。以下に乱数を生成するrand.cとバブルソートを行うbubblesort.cを記載します。これに処理時間を出力するようにしてもらいたいのですが、どうしたらいいですか?解説とソースファイルをよろしくお願いします。 rand.c #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 1000 int num[N]; int makeDataFile ( void ) { int i; FILE *fp; char s[100]; int num[N]; srand ( ( unsigned )time ( NULL ) ); fp = fopen ("rand1.txt", "w" ); if ( fp == NULL ) exit(1); for ( i = 0; i < N; i++ ){ fprintf ( fp, "%d\n", rand()%100 ); } fclose ( fp ); fp = fopen ( "rand1.txt", "r" ); if ( fp == NULL ) exit(1); while( fgets ( s, sizeof (s), fp ) ) { printf ( s ); } fclose ( fp ); return N; } bubblesort.c #include <stdio.h> #include <time.h> extern int makeDataFile ( void ); extern int num[]; void BubbleSort ( int x[] , int n ); void Show ( int x[] , int n ); int comp; int swap; void BubbleSort ( int x[] , int n ) { int i, j, tmp; for ( i = 0; i < n-1; i++ ) { for ( j = n-1; j > i; j-- ){ comp++; if ( x[i] > x[j] ){ swap++; tmp = x[j]; x[j] = x[i]; x[i]= tmp; Show ( x , n ); } } } } void Show ( int x[] , int n ) { while ( n-- ) printf ( "%d " , *x++ ); printf ( "\n" ); } int main(void) { int i, j, n , tmp; FILE *fp; comp = 0; swap = 0; n = makeDataFile(); fp = fopen ( "rand1.txt", "r" ); if ( fp == NULL ) return 1; for ( i = 0; i < n; i++ ){ fscanf ( fp, "%d", &(num[i] ) ); } fclose ( fp ); printf ( "\nbefore bubblesort\n" ); Show ( num , n ); printf ( "\n" ); printf ( "progress bubblesort\n" ); BubbleSort ( num , n ); printf ( "\n" ); printf ( "after bubblesort\n" ); Show ( num , n ); printf ( "\n" ); printf ( "count of comparisons : %d\n" , comp ); printf ( "count of swap : %d\n" , swap ); return 0; }

  • フーリエ変換のC言語プログラムについて

    正弦波(およびガウス性雑音)をフーリエ変換(離散)→逆フーリエ変換するというプログラムを組みました。正弦波をフーリエ変換すると実部は2回ピークがくるはずなのですが、すべて「0.000000」または「-0.000000」と表示されてしまいます。虚部は正常なようで実装の仕方もさほど違わないので、何が問題なのかわからずにいます。念のためコードはすべて載せますが、該当箇所は関数Fourierの fp = fopen("reX.txt", "w"); //書き込む あたりです。問題点を教えていただけないでしょうか。お願いします。 //gauss.txt, sin.txt:発生させたガウス性雑音&正弦波 //reX, imX:フーリエ変換の実部と虚部 //re-1, im-1:逆フーリエ変換の実部と虚部 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #define PI 3.14159265358979323846 #define N 256 //n:長さ, w:角周波数, p:位相(phase), a:振幅 void SinCurve(int n, double w, double p, double a) { FILE *fp; double x; int t; fp = fopen("sin.txt", "w"); //書き込むので"w" if(fp == NULL) { printf("file open error\n"); } else { for(t = 0; t < n; t++) { x = a * sin( w*(double)t + p ); fprintf(fp, "%f\n", x); } } fclose(fp); } //n:長さ, s:分散, m:平均 void Gauss(int n, double s, double m) { FILE *fp; double x, x1, x2, y1; int t; srand((unsigned) time(NULL)); fp = fopen("gauss.txt", "w"); //書き込むので"w" if(fp == NULL) { printf("file open error\n"); } else { for(t = 0; t < n; t++) { x1 = ( (double)rand() + 1.0 ) / ( (double)RAND_MAX + 2.0); x2 = ( (double)rand() + 1.0 ) / ( (double)RAND_MAX + 2.0); y1 = pow(-2.0*log(x1), 0.5) * cos(2.0*PI*x2); y1 = s * y1 + m; fprintf(fp, "%f\n", y1); } } fclose(fp); } //ファイル名sのデータをフーリエ変換し、実部と虚部をreX, imXに保存 void Fourier(int num, char *s) { FILE *fp; int k, n; double largeX, x[N+100], t; fp = fopen(s, "r"); //読み込み if(fp == NULL) { printf("file open error\n"); } else { // printf("%s\n", s); for(k = 0; k < num; k++) { fscanf(fp, "%lf", &x[k]); printf("x[%d]=%f\n", k, x[k]); } } fp = fopen("reX.txt", "w"); //書き込む if(fp == NULL) { printf("file open error\n"); } else { for(k = 0; k < num; k++) { largeX = 0.0; t = 2.0*PI*(double)k / (double)N; for(n = 0; n < num; n++) { largeX += x[n] * cos((double)n*t); // printf("%f\n", largeX); } fprintf(fp, "%f\n", largeX); printf("reX[%d]=%f\n", k, largeX); } } fp = fopen("imX.txt", "w"); //書き込む if(fp == NULL) { printf("file open error\n"); } else { for(k = 0; k < num; k++) { largeX = 0.0; t = 2.0*PI*k / (double)N; for(n = 0; n < num; n++) { largeX -= x[n] * sin(n*t); } fprintf(fp, "%f\n", largeX); } } fclose(fp); } void InverseFourier(int num) { FILE *fp; int k, n; double a[N+100], b[N+100], x, t; //a:reX, b:imX fp = fopen("reX.txt", "r"); //読み込み if(fp == NULL) { printf("file open error\n"); } else { for(k = 0; k < num; k++) { fscanf(fp, "%lf", &a[k]); // printf("a[%d]=%f\n", k, a[k]); } } fp = fopen("imX.txt", "r"); //読み込み if(fp == NULL) { printf("file open error\n"); } else { for(k = 0; k < num; k++) { fscanf(fp, "%lf", &b[k]); // printf("b[%d]=%f\n", k, b[k]); } } fp = fopen("re-1.txt", "w"); //読み込み if(fp == NULL) { printf("file open error\n"); } else { for(n = 0; n < num; n++) { x = 0.0; t = 2.0*PI*(double)n / (double)N; for(k = 0; k < num; k++) { x +=a[k] *cos(k*t) - b[k] *sin(k*t); } x /= (double)N; fprintf(fp, "%f\n", x); // printf("x[%d]=%f\n", n, x); } } /* fp = fopen("im-1.txt", "w"); //読み込み if(fp == NULL) { printf("file open error\n"); } else { for(n = 0; n < num; n++) { x = 0.0; for(k = 0; k < num; k++) { t = 2.0*PI*(double)k / (double)N; x = x + a[k] *sin(n*t) + b[k] *cos(n*t); } x /= (double)N; fprintf(fp, "%f\n", x); } } */ fclose(fp); } int main(void) { SinCurve(N, PI/8.0, 0.0, 1.0); // Gauss(N, 1.0, 0.0); Fourier(N, "sin.txt"); // Fourier(N, "gauss.txt"); InverseFourier(N); return 0; }

  • C言語の質問です。

    前にも質問したのですがなかなかうまくいかないのでよろしくお願いします。 データの書いてあるファイルを読み込んで処理するプログラムを書きたいと考えています。 読み込むデータ 0.012500 0.499167 1.382500 1.534444 2.489167 3.635000 3.775000 5.407500 5.705000 5.916667 6.115833 6.295278 6.825278 7.079722 . . . . この様な数値のかいてあるデータを使って0.5ずつに区切ってその中に何個データがあるか数えたいと考えています。(データは1万5千個以上あります) 例えば上のデータで考えると 0~0.5の範囲のデータは2個 0.5~1の範囲のデータは0個 1~1.5の範囲のデータは1個 1.5~2の範囲のデータは1個 2~2.5の範囲のデータは0個。。。 という風に数えるプログラムにしたいです。 僕が分からないところはどのように場合分けしていくか。。。です。 #include<stdio.h> //#include<process.h> int main(void) { FILE *fp; double n; int cnt,i,Cnt; fp=fopen("1.dat","r"); if(fp==NULL) { printf("file open error!!\n"); exit(1); } i=0; cnt=0; Cnt=0; while(fscanf(fp,"%lf\n",&n)!=EOF){ if(i<=n<(i+0.5)){ cnt++; printf("%lf %d\n",i,cnt); } else if((i+0.5)<=n<(i+1)){ Cnt++; printf("%lf %d\n",i,Cnt); } else{ i++; } } fclose(fp); return 0; } 僕の考えはデータを読み込む 変数 i を使って if文で i <= n <i+0.5の範囲のときはcntを足していく     i+0.5<= n <i+1の範囲のときはCntを足していく それ以外のときは i を+1して同じことを繰り返す というようなやり方を考えました。 しかしうまくいきませんでした。 どのようにすればよいでしょうか。 よろしくお願いします。

  • C言語 ファイルの読み込みについて

    以下のようなプログラムを実行します \nで改行が行われません。なぜでしょうか? #include <stdio.h> void main () { FILE *fp; double a, b; int count=0; fp = fopen("arm_x.csv","r"); while(1) { fscanf(fp,"%lf%lf\n",&a,&b); printf("%f::%f\n",a,b); count++; if(count==10)break; } fclose(fp); } csvファイルは 0.0 0.1 0.2 0.3 0.4 0.5 0.1 0.2 0.3 0.4 0.5・・・ 0.2 0.3 0.4・・・・・・・・・ : : です。 実行結果はこのようになってしまいます。 0.0 0.1 0.2 0.3 0.4 0.5 : :

  • C言語の計算についての質問です.

    C言語の計算についての質問です. 1 2 3 4 5 6 2 3 4 5 6 7 3 4 5 6 7 8 というようなファイルを行ごとに読み込んで、列ごとの和を算出させたいと考えています. 以下のようなプログラムをテスト作成してみたのですが,『 b=1のときのa[1] + b=2のときのa[1] 』のような計算ができません. どのようなプログラムを作成すればこの問題が解決できるか教えてください. #include <stdio.h> #include <string.h> int main(void) { FILE *fp; int i, j, k, no, b; double a[12]; double c[3]; char buffer[1024]; for(i=1; i<=2; i++) { sprintf(buffer, "PIVdemo_00%d%d.txt", i/10, i%10); printf("%s \n", buffer); fp = fopen(buffer,"r"); for(b=1; b<=12; b++) { fscanf(fp, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9], &a[9], &a[10], &a[11], &a[12]); printf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf \n", a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[9], a[10], a[11], a[12]); } for(b=0; b<=2; b++){ c[3]=a[b] + a[b+1]; printf("%lf", c[3]); putchar('\n'); } fclose(fp); } return (0); }

専門家に質問してみよう