ページ 11

ファイル入出力について

Posted: 2012年5月07日(月) 08:32
by pblc
試行回数10万回でxorshift法を用いて(0,1)の一様乱数の度数分布を作成する問題なのですが、
ファイルを出力する際に10個の値がすべて0になってしまいます。
使用環境はxcode3.2.6でmac osの10.6.8です。
学校の環境では同じコードで上手く出力されていたはずなのですが…
よろしければご教授ください

コード:

#include<stdio.h>

unsigned long xorshift(){
	static unsigned long x=123456789, y=362436069, z=521288629, w=88675123;
	unsigned long t;
	t = (x^(x<<11)); x=y;y=z;z=w;
	return (w=(w^(w>>19))^(t^(t>>8)));
}

int main(){
	int x,a=0,b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;
	double  y;
	FILE *file;
	file = fopen("test.txt","w");
	for(x=0;x<=99999;x++){
		y=xorshift()/4294967295.0;
		if(y>=0.0 && y<=0.10){
			a++;
		}
		else if(y>=0.10 && y<=0.20){
			b++;
		}
		else if(y>=0.20 && y<=0.30){
			c++;
		}
		else if(y>=0.30 && y<=0.40){
			d++;
		}
		else if(y>=0.40 && y<=0.50){
			e++;
		}
		else if(y>=0.50 && y<=0.60){
			f++;
		}
		else if(y>=0.60 && y<=0.70){
			g++;
		}
		else if(y>=0.70 && y<=0.80){
			h++;
		}
		else if(y>=0.80 && y<=0.90){
			i++;
		}
		else if(y>=0.90 && y<=1.0){
			j++;
		}
	}
    fprintf(file,"%d\n",a);
    fprintf(file,"%d\n",b);
    fprintf(file,"%d\n",c);
    fprintf(file,"%d\n",d);
    fprintf(file,"%d\n",e);
    fprintf(file,"%d\n",f);
    fprintf(file,"%d\n",g);
    fprintf(file,"%d\n",h);
    fprintf(file,"%d\n",i);
    fprintf(file,"%d\n",j);
	fclose(file);
	return 0;
}

Re: ファイル入出力について

Posted: 2012年5月07日(月) 11:17
by softya(ソフト屋)
こちらでは、ちゃんと動作しますね。
Windows cygwin gcc 4.3.4です。

なので、そちらでないと再現確認はできないと思われます。
まず、xorshiftの戻り値が想定したものかprintfで確認されてはどうでしょうか?

Re: ファイル入出力について

Posted: 2012年5月07日(月) 12:45
by あたっしゅ
Mac の OS X はよく知らないんで、
はずしてるかもしれませんが、
学校のは 32bit モード、
家のは 64bit モードで
コンパイルしてるのではないですか?


16行目 y=xorshift()/4294967295.0;

4294967295 は FFFFFFFF(16)で 32bit 目一杯という数値ですよね。
xorshift() の値が 32bit で表せる数値を越えていると、
4294967295.0 で割っても 1.0 より大きくなって
a から j のどれもインクリメントされません。

softya さんのいうとおり、
xorshift の戻り値が想定したものか
printf で確認されてはどうでしょうか?

3行目 unsigned long xorshift(){

unsigned long ではなく、__uint32 使うとか。
xcode には、ないか ?


あと、「ご教授(きょうじゅ)」は、「ご教示(きょうじ)」ね。

Re: ファイル入出力について

Posted: 2012年5月07日(月) 12:53
by h2so5
32bitモードでは正常に作動しました。
64bitモードでは sizeof(unsigned long) == 8 なので上手く動きません。

Re: ファイル入出力について

Posted: 2012年5月07日(月) 17:02
by box
pblc さんが書きました: ファイルを出力する際に10個の値がすべて0になってしまいます。
当方の環境 gcc 4.5.2 (OSは32ビット)では、うまくいきます。ところで、
pblc さんが書きました:

コード:

	int x,a=0,b=0,c=0,d=0,e=0,f=0,g=0,h=0,i=0,j=0;
配列か何かを使った方が、コードがすっきりすると思います。
10個の値でなく、100個でもこういう風に書くのかな?という疑問があります。
それから、
pblc さんが書きました:

コード:

		if(y>=0.0 && y<=0.10){
		else if(y>=0.10 && y<=0.20){
仮に、yの値が「ちょうど0.10」だった場合、2回カウントしますね。そういう仕様ですか?
MECE(もれなく、ダブりなく)の原則に反しているように思います。

Re: ファイル入出力について

Posted: 2012年5月07日(月) 17:21
by beatle
box さんが書きました:
pblc さんが書きました:

コード:

		if(y>=0.0 && y<=0.10){
		else if(y>=0.10 && y<=0.20){
仮に、yの値が「ちょうど0.10」だった場合、2回カウントしますね。そういう仕様ですか?
MECE(もれなく、ダブりなく)の原則に反しているように思います。
else ifですから、ダブりはないのでは?

Re: ファイル入出力について

Posted: 2012年5月07日(月) 19:03
by box
beatle さんが書きました: else ifですから、ダブりはないのでは?
おっしゃるとおりですね。
失礼いたしました。>質問者さん

# 謝っといて何ですが、何となく紛らわしい感じがする。

Re: ファイル入出力について

Posted: 2012年5月07日(月) 23:42
by pblc
返信ありがとうございます。
xorshiftの値をprintfしてみると、確かに64bitぐらい?の値になっていました…。
xcodeを32bitモードにする方法がわからないので2^64で割ってみたら、これなら上手く行きそうです。
あと配列にしたほうがいいとは個人的にも思っていたのですが、
初心者な上にコードを書くのが久しぶりすぎてそこまで気が回りませんでした…。
誤用とともに以後気をつけるようにします。

Re: ファイル入出力について

Posted: 2012年5月07日(月) 23:48
by softya(ソフト屋)
gccであれば、「整数型 - Wikipedia」
http://ja.wikipedia.org/wiki/%E6%95%B4% ... B.E5.90.8D
にあるuint32_tを使えば32bitは保証されます。要stdint.h

あとコンパイルオプションで、-std=c99を付けないとコンパイルが通らないかもしれません。

Re: ファイル入出力について

Posted: 2012年5月08日(火) 00:01
by pblc
uint32_t使ったら32ビットになりました!ありがとうございます。
コンパイルオプションは(こちらの環境では?)付けなくても良かったみたいです。