質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

4回答

2246閲覧

1000000回繰り返しすべての試行回数を足すプログラム

Shotayanagi

総合スコア5

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/07/15 15:22

C言語 プログラミングに関する質問です。

0~9までの番号が振られたくじがあり、出る確率はすべて等しいものとするとくじ10本をすべて引き切るまでに何回くじを引く必要があるか求め、そのシュミレーションを1000000回行った時の回数の合計と平均値を求めよ。ただしくじは何度でも引けるものとし、rand関数を用いることとする。

という問いに関してなのですが、以下のプログラムを実行すると合計が18億前後、平均は1800ほどになってしまい、本来平均20~40ほどとなるはずなのに大きくずれが生じてしまいます。個人的に不安なのが変数を宣言する位置とそもそもdo文をこのような形でfor文に取り込むことが出来るかという点、また1000000回シュミレーションしたときの合計(sum)を求めるところです。
まだプログラミングを始めて間もなく、わからないことばかりなので教えていただけると幸いです。。。
よろしくお願いします。

#include<stdio.h> #include<time.h> #include<stdlib.h> /*0~9の数字を返す*/ int kuji(){ return (rand()>>2) % 10; } int main(){ int i; double avg=0;        /*1000000回試行したときの平均値*/ unsigned short Flags = 0; /*各値のくじを引いたか下位10ビットで記憶する変数*/ unsigned int N = 0;    /*くじを引いた回数カウンター*/ unsigned sum=0;       /*1000000回引いた時の回数の合計*/ /*for文にdo文を入れdo文を1000000回繰り返す*/ for(i=0; i<1000000; i++){ sum += N;      /*1000000回分のNの合計*/ avg = sum/1000000; /*1000000回引いた時の平均値*/ srand((unsigned) time(NULL)); /*0~9のくじを引き切るまでの回数を求める*/ do{ ++N; Flags |= (1 << kuji() ); }while( Flags != 0x3FF); } printf("sum = %u\n",sum);   /*1000000回引いた時の回数の合計を表示*/ printf("avg = %.2f\n", avg ) ;/*1000000回引いた時の平均の回数を表示*/ return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/07/15 15:28

どうなるのが正解なんでしょうか
Shotayanagi

2020/07/15 15:55

1000000回シュミレーションを繰り返した時、合計で何回くじを引いたか、とその合計を1000000で割った平均値を表示するという問題です。 分かりずらくてすみません… だいたい平均値は20-40前後、合計はその1000000の値が表示されれば問題なしです…
guest

回答4

0

C

1#include <stdio.h> 2#include <time.h> 3#include <stdlib.h> 4 5int kuji(){ 6 return (rand() >> 2) % 10; 7} 8 9int main(void) 10{ 11 srand((unsigned)time(NULL)); 12 13 const int imax = 1000000; 14 unsigned int sum = 0; 15 16 for (int i = 0; i < imax; i++) { 17 unsigned short Flags = 0; 18 unsigned int n; 19 for (n = 0; Flags != 0x3ff; n++) { /*# 修正 */ 20 Flags |= 1 << kuji(); 21 } 22 sum += n; 23 } 24 25 double avg = (double)sum / imax; 26 27 printf("sum = %u\n", sum); 28 printf("avg = %.2f\n", avg); 29 30 return 0; 31}

投稿2020/07/15 16:09

編集2020/07/15 22:57
Daregada

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SHOMI

2020/07/15 16:20 編集

>for (n = 1; Flags != 0x3ff; n++) 一周目ループ終了時にnが2になるので、初期値を0にしないと一回余分にカウントしますよ。
Daregada

2020/07/15 16:21

おっと、直します。
Shotayanagi

2020/07/16 01:36

ご丁寧に全文つけてくださり、ありがとうございます! 1000000も文字に代入してしまえばだいぶ見やすくなりまりますね! 助かりました!
guest

0

srand((unsigned) time(NULL));

これは最初の一回だけ、実行するようにしましょう。
1ms以内にループが回ると、同じ乱数列が出てきてしまいます

また、

avg = sum/1000000; /1000000回引いた時の平均値/

これがループの中にあるのが意味不明です。

投稿2020/07/15 16:01

y_waiwai

総合スコア87782

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SHOMI

2020/07/15 16:03

>1ms以内 1秒以内ですよね
y_waiwai

2020/07/15 16:06

ああ、C言語のヤツはそうですね。 ご指摘ありがとうございます
Shotayanagi

2020/07/16 01:34

なるほど。ご回答ありがとうございます!
guest

0

ベストアンサー

出題通りのコードになっていません。

  • sumの加算タイミングがおかしい。

試行回数を求める前に加算しています。最後のループ時の試行回数が加算されません。

  • ループごとにN,Flagsを0クリアしていない。

2回目以降は1度しか振らず、N前ループの値+1になる。
初回ループで10回の試行ですべての目が出たとしても、それだけでsum1793293664(sum加算タイミング修正前は1792293655)になります。

  • ループごとにsrandで初期化している。

1秒以内にループが終わった場合次のループで使われる乱数の値が前のループと同じになる。

  • avgの計算が整数演算になっている。

小数点以下が求まりません。

C

1 srand((unsigned)time(NULL)); 2 for (i = 0; i < 1000000; i++) { 3 N = 0; 4 Flags = 0; 5 do { 6 ++N; 7 Flags |= (1 << kuji()); 8 } while (Flags != 0x3FF); 9 sum += N; 10 } 11 avg = sum / 1000000.0;

結果

sum = 29282182 avg = 29.28

投稿2020/07/15 15:57

編集2020/07/15 16:32
SHOMI

総合スコア4079

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Shotayanagi

2020/07/16 01:33

ご指摘ありがとうございます! 丁寧に実行結果までつけてくださって助かりました!
guest

0

出る回数が等しい乱数をシミュレーションしたいのであればこの場合は乱数としてi%10を疑似乱数列としてつかってください。そうするとご希望どおりの出現率がおおよそ等しくなります。
シードごとの乱数の分布を知りたいのであれば、シードも保存してください。

投稿2020/07/16 00:40

kokorohamoe

総合スコア190

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問