• 締切済み

乱数の取得

キー操作をした時に複数の乱数を習得させようと思っています。 【キ─操作関数】  int num[3] = {11, 22, 33}; ←初期化のため数字は適当です。  srand((unsigned int)time(NULL))  for(int i=0; i<=3; i++)  {   num[i] = rand % 10;  } 上記のプログラムを書いています。 num[0]、num[1]、num[2]にそれぞれ0~9の乱数が入ると思うのですが、 num[0]にしか乱数が入りません。 num[1]、num[2]には同じ数字(恐らくtimeで取得した数字?)が入っています。 何かお気づきの点がありましたらアドバイスお願い致します。

  • Key00
  • お礼率12% (2/16)

みんなの回答

回答No.9

No.2、6です。 >ループ条件ですが、 >for(int i=0; i<=3; i++)としたのは、今回は乱数を3つ必要でしたが後々4つ使用するためです。 >int num[3]ではnum[0]、num[1]、num[2]の3つしか使用してはいけないが、 >num[4]が発生したところで使用せずとも問題ないと思っていたのですが…これも認識が違っていますでしょうか? すでに回答が付いていますが、間違いです。 わかりやすい例えをしましょう。 --------- 机の上に空のコップが「3つ」あります。 一つのコップには「一回だけ」ジュースを注ぐこととし、計「4回」ジュースを注ぎました。 3回はコップにジュースを注ぐことができましたが、最後の一回は? コップが無いため、机と床を濡らしてしまいました。 --------- これが質問者さんの行っていることです。 実際、私の環境では、num[3] = rand()の実行で例外エラーが発生します。 どうしても、後で増やす必要があるのであれば、以下のような方法があります。(一部省略) --------- #define MAX 3 int num[MAX]; for(i=0; i<MAX; i++) --------- 配列の要素数とループの上限をあわせる為に同じ定数値を使うことです。 それによりループ回数と配列の要素の食い違いを防げます。 プログラムは「よくわからないけど、動いているからいいや」では駄目です。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.8

 メモリ破壊を目視出来るようにコーディングしました。ただし配列(変数)のメモリへの割り付け方はコンパイラおよびリンカによって変化しますので,この例のようにnumとxが順にメモリ配置されるかは保証できません。 【検証コード】 #include <stdio.h> #include <stdlib.h> #include <time.h> void main() { static int num[3] = {11, 22, 33}; static int x[1]={44}; srand((unsigned int)time(NULL)); printf("0x%08X:x[0]=%d\n", (unsigned long)&x[0],x[0]); for(int i=0; i<=3; i++) { num[i] = rand() % 10; printf("0x%08X:num[%d]=%d\n", (unsigned long)&num[i], i, num[i]); } printf("0x%08X:x[0]=%d (x[0]がnum[4]で上書きされる。本当は44が返されるべき。)\n", (unsigned long)&x[0],x[0]); return; } 【実行結果】 0x00817044:x[0]=44 0x00817038:num[0]=8 0x0081703C:num[1]=3 0x00817040:num[2]=7 0x00817044:num[3]=1 0x00817044:x[0]=1 (x[0]がnum[4]で上書きされる。本当は44が返されるべき。) 【説明】  上記実行結果の「0x」で始まる16進数はメモリのアドレスで,x[0]とnum[3]が同じアドレスであることを確認して下さい。  (配列も変数も全てメモリ上に配置されていますので同じメモリアドレスを指しているのであれば値が共有されていることになります。)  int num[3] 宣言はnumを3つ確保するだけなので使える範囲はnum[0]~num[2]までです。しかしC言語(C++)ではnum[3]に値を入れる事は禁止されていない為,num[3]に書き込むことが出来ます。この結果num[3]と同じメモリアドレスのx[0]が意図せずに壊されます。  このあとにx[0]を参照する処理があれば,値が破壊されている為,正常に処理を継続することが出来ません。  この例のように意図しないメモリを書き込み(メモリ破壊)があると,コードからのデバッグが難しくよくバグの原因となります。

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

>for(int i=0; i<=3; i++)としたのは、今回は乱数を3つ必要でしたが後々4つ使用するためです。 >int num[3]ではnum[0]、num[1]、num[2]の3つしか使用してはいけないが、 >num[4]が発生したところで使用せずとも問題ないと思っていたのですが…これも認識が違っていますでしょうか? 使用しているつもりがなくても、代入している以上はどこかのメモリ領域を書き換えています。 「使わないから問題ナシ!!」の結果が、関数からのリターンアドレスを書き換えてて吹っ飛ぶのも問題ナシですか? バッファオーバーフロー系の不具合は、表面化する箇所がわかりにくい場合があるので注意が必要です。 # オープンソースなどでもときどき出てくるくらいよくあるミス…だったりしますけどね。

回答No.6

No.2です。 >使用したいのはnum[0]、num[1]、num[2]なので… >int num[3]で配列を3つ用意する。という意味ではないのでしょうか? 記憶違いでしたらすみません。 これはあっています。しかし、No.2の内容を理解されていますか? 再度書きます。 ------------- 考え方はあっていますが、ループ条件が違います。 for(int i=0; i<=3; i++) は、iが「0から3以下」ならループが継続されます。 従ってiは、「0」「1」「2」「3」の4回ループされます。 int num[3]では、num[]の要素は、num[0]、num[1]、num[2]までしか使用してはいけません。 ------------- num[]は「3つ」しか用意していないのに、ループではnum[i]により「num[3]」、つまり「4つ目」になってしまう条件が発生することを、No.1氏も私も指摘しています。 ブレークポイントについては、「非効率」とありますが、確かにそれもひとつはありますが確認すべき項目を間違っているとしか思えません。

Key00
質問者

補足

ブレイクポイントについては理解が足りておりませんでした。 お手数おかけして申し訳ありません。 プログラムについては解決致しました。 アドバイスありがとうございます。 ループ条件ですが、 for(int i=0; i<=3; i++)としたのは、今回は乱数を3つ必要でしたが後々4つ使用するためです。 int num[3]ではnum[0]、num[1]、num[2]の3つしか使用してはいけないが、 num[4]が発生したところで使用せずとも問題ないと思っていたのですが…これも認識が違っていますでしょうか? 何度も申し訳ありませんがご教授お願い致します。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.5

>確認用にnum[0]などを書き、03の部分にブレイクポイントを打って確認しました。 一回目のbreakで、num[1]とnum[2]の確認もしているわけではないですよね?

Key00
質問者

補足

すみません…ブレイクポイントについての理解が足りていませんでした。 1回目のブレイクでnum[1]、num[2]も確認しておりました…。 解決致しましたありがとうございます。

  • goosyu
  • ベストアンサー率58% (36/62)
回答No.4

→#2の回答者さんの指摘以外,特に問題がありそうなところはありません。セミコロンが抜けている,randの括弧が足りない点を考えると,実際のソースと他に差分がないか確認した方がいいと思います。 差がほとんどありませんが,サンプル載せておきます。 #include <stdio.h> #include <stdlib.h> #include <time.h> void main() { int num[3] = {11, 22, 33}; srand((unsigned int)time(NULL)); for(int i=0; i<3; i++) { num[i] = rand() % 10; } printf("num[0]=%d,num[1]=%d,num[2]=%d\n", num[0], num[1], num[2]); }

Key00
質問者

お礼

サンプル有難うございます。 こちらを拝見し問題解決致しました。 取得した乱数を元に下の作業を振り分けたかったのですが、 num[1]、num[2]に乱数が入らなかったため作業分けが出来ていませんでした。 サンプルで確認しましたところ、num[i] = rand() % 10;の下に作業の振り分けを書いておりました…。 ループ1度目で振り分けされてしまうのでnum[1]、num[2]に乱数のループが入らなかったのではと思っています。 アドバイスありがとうございました。

  • yamaj_biz
  • ベストアンサー率71% (10/14)
回答No.3

まさか…とは思うのですが、 randっていう変数を作ってないですよね? 乱数の取得は関数なので「rand() % 10;」だと思います。

Key00
質問者

補足

↑の記述ミスです。 プログラムでは num[i] = rand() % 10; を使用しています。

回答No.2

>>i[3]ってドコでしょう??? >配列は0から使用されるので"3回回す"で[0]、[1]、[2]にそれぞれ数字が入ると思っていたのですが違うのでしょうか? 考え方はあっていますが、ループ条件が違います。 for(int i=0; i<=3; i++) は、iが「0から3以下」ならループが継続されます。 従ってiは、「0」「1」「2」「3」の4回ループされます。 int num[3]では、num[]の要素は、num[0]、num[1]、num[2]までしか使用してはいけません。 >>どうやって確認しました? >VisualStudioでブレイクポイントをつけて確認しました。 どこにブレークポイントを張り、どの変数の内容を確認しましたか? rand()がある程度の分散値を出力するなら、値は変わっているはずですよ。

Key00
質問者

補足

使用したいのはnum[0]、num[1]、num[2]なので… int num[3]で配列を3つ用意する。という意味ではないのでしょうか? 記憶違いでしたらすみません。 01{ 02 num[i] = rand() % 10; 03 num[0]; 04 num[1]; 05 mum[2]; 06} 左端は行番号だと思って下さい。 確認用にnum[0]などを書き、03の部分にブレイクポイントを打って確認しました。 VisualStudioの扱いも不慣れなもので…非効率な事をしていましたらすみません。

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

>num[i] = rand % 10; rand()ですよね? >for(int i=0; i<=3; i++) iが、0から「3」まで実行されます。 i[3]ってドコでしょう??? >num[0]にしか乱数が入りません。 >num[1]、num[2]には同じ数字(恐らくtimeで取得した数字?)が入っています。 どうやって確認しました?

Key00
質問者

補足

回答有難うございます。 rand()です。書き間違えました;; >i[3]ってドコでしょう??? 配列は0から使用されるので"3回回す"で[0]、[1]、[2]にそれぞれ数字が入ると思っていたのですが違うのでしょうか? >どうやって確認しました? VisualStudioでブレイクポイントをつけて確認しました。

関連するQ&A

  • 乱数について

    Visual Studio2008を使っています。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void){ int i; srand(time(NULL)); i=rand(); printf("%d\n",i); return 0; } 乱数を作るために上のようなプログラミングを作りました。 これを「ソリューションのビルド」すると 【warning C4244: '引数' : 'time_t' から 'unsigned int' への変換です。データが失われる可能性があります。】 と出ます。 このまま行っても乱数が出来るのですが どうしたらいいのでしょうか? 8行目を srand(time_t(NULL)); srand((unsigned)time(NULL)); と変えればいいのでしょうか? time_tでやると乱数が同じ値しか出てきません。 教えてください。

  • 乱数で交互に偶数、奇数が、、、。

    C言語で、確率2分の1で0と1を 出そうとして、rand,srand,timeを使って やってみたのですが、ちょうど、0と1が 交互に出てしまいます。何度やっても 変わりません。ただ、1と0が逆になる だけ。こんな感じで0101010101か1010101010 つまり、乱数で奇数と偶数が 交互に発生しているみたいうまくいきません。 なにか、別の方法ありますか? --------------------------------------- srand((unsigned int)time(NULL)); s=rand()%2 これで、やってます。

  • 乱数の最大値

    C言語で0~Nまでの乱数を発生させる場合、 srand((unsigned) time(NULL)); rand()%N; とやりますよね。 このやり方だと、発生する乱数はRAND_MAX以下しかできません。 RAND_MAX以上の値を発生させるにはどうすればいいのでしょうか?

  • 乱数について

    C の入門書を1冊読み終え、簡単なプログラムを作成しようとしているのですが、 早速分からないことが出たので教えて頂ければと思います。 --------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int num; int i = 0; while( i < 4 ){ srand(time(NULL)); num = rand()%100; printf("%d\n", num); i++; } return 0; } --------------------------------------------- 上記を実行したのですが、秒数を乱数の種としているため4回とも同じ値を取得してしまいます。 より高精度に秒数を取得することは可能でしょうか? もしくはこのようなかたちで4回ともに異なる数を得ることが出来る方法がありましたら教えて頂きたいと思います。

  • 乱数について・・・

    (1)1,2,3,4の整数のどれかを乱数で発生させる方法 (2)0~1までの実数を発生させる方法 を教えていただけないでしょうか?(a.outするたびに値が変わってほしいです。) ※一応、下のプログラムにあるように実行するたびに違う乱数がanswerに入るようにはできたのですが、いまいち理解できていません。軽い説明や参考URLなども教えてもらえたら助かります。 よろしくお願いします。 #include<time.h> int main() { unsigned short time_a,time_b; unsigned long answer; time_a = time(NULL); time_b = time_a; srand(time_b); answer = rand(); printf("答えは = %d\n",answer); }

  • 型変換??

    int RANDOM_FUNCTION( int n ) { return (int)( rand() / (float)RAND_MAX * n ); } について Q1.この関数は0からn-1までの乱数を作るそうなのですが,何故ですか? 0<=rand()<=RAND_MAX だから0からnまでの乱数ができるような気がするのですが. Q2.RAND_MAXではなく(float)RAND_MAXとキャストしてある意味は何ですか? Q3.srand((unsigned)time(NULL));と srand((unsigned int)time(NULL));では何か違いますか? Q4.  static int first = 0; if (first == 0){ srand((unsigned)time(NULL)); first = 1; } という処理でsrand((unsigned)time(NULL));は最初の一回だけ呼び出されるようになっているようですが,この部分を srand((unsigned)time(NULL)); というように毎回呼び出すようにするとどうなりますか? 一回呼び出すだけで乱数系列の初期値が呼び出される時に変化しているのですか? Q5.この関数とは関係ない質問ですが,例えば a:int型 b:int型 c:double型 d:float型 のとき d = a / b + c という演算は 1 a:int型,b:int型より(a / b)の結果はint型(小数になった場合は小数点以下切り捨て) 2 (a / b):int型,c:double型,int<doubleより (a / b + c)の結果はdouble型 3 d:float型,『=のあるときは左辺の型に合わせる』よりdはfloat型 というように型変換されているという解釈でいいのでしょうか??

  • 乱数発生

    #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) {int y, m, l; srand( (unsigned)time( NULL ) ); y=rand() % 2500 + 1600; m=rand() % 12 + 1; l=rand() % 29 + 1; printf("西暦%d年%d月%d日",y,m,l); return(0); }今回は乱数発生でランダムにだされた西暦年月日をつくりましたが、y=rand() % 2500 + 1600; というのがありこれはyという乱数が2500以下1600以上という意味なのですがなぜかプログラムを実行しても3000いくつとか4000いくつなんてのもでてきます。m=rand() % 12 + 1;はちゃんと12以下1以上でできるのですがなぜですか?本当にわかりません。是非だれか教えてください。

  • c言語で乱数を扱うときの

    乱数を初期化するために srand((unsigned)time(NULL)というのを使いますが これはどういう意味を表してるんでしょうか? timeは1970年から経過した時間を表していることは分かりますし unsignedは符号ビットをなくして表せる数を倍にしてることも分かりますが、 NULLって何のために書いてあるのでしょうか?

  • C++で乱数を重複しないように発生させる

    C++で乱数を重複しないように発生させるようにプログラムを変更しろと言われたのですが、できません。 教えていただきたいです。 #include<iostream> #include<cstdlib> #include<cstring> #include<ctime> using namespace std; int main() { int i,n; int *p; cout<<"何個記憶しますか?"<<endl; cin>>n; p=new int[n]; if(p==NULL){ cout<<"記憶域の確保に失敗しました。"<<endl; return 1; } srand((unsigned)time(NULL)); rand(); i=0; while(i<n){ p[i]=1+(int)((double)rand()/(RAND_MAX+1.0)*75); if(p[i]==p[i]) cout<<"p["<<i<<"]の値"<<p[i]<<endl; i++; } delete[] p; return 0; }

  • 毎回違う乱数を生成するにはどうしたらいいでしょうか

    C言語の初心者です。よろしくお願いいたします! 乱数に関する質問:毎回違う乱数を生成するにはどうすればいいでしょうか。 学校の講義の中に  >>time() は1970 年1 月1 日0 時0 分(標準時)からの経過秒数を返 すため,1 秒以内に何度も実行すると,同じ数字で乱数を初期化す ることになり,結果も同じになってしまう. という記述がありますが、時間を置いてから、実行しても同じ結果となりました。 その一 #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> int main(void) { double x,y; int i,index=0; double a,n; printf("How many trials?..."); scanf("%lf",&n); for (i=0;i<n;i++) { x=rand()/(RAND_MAX+1.0); y=rand()/(RAND_MAX+1.0); if((x*x+y*y)<1) index++;} a=4*index/n; printf("Result is %.2f(%.2f)",a,sin(-a)); return 0; } その二 #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int a; srand((unsigned)time(NULL)); a=(int)(rand()/(RAND_MAX+1.0)*10); printf("%d\n",a); return 0; } お忙しい中、教えていただけたらうれしいです。

専門家に質問してみよう