掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.27081

擬似乱数
投稿者---asc(2006/06/06 22:55:14)


普通に0~99の擬似乱数を30個表示しようとすると表示される乱数の値に重複ことがあります。

これを重複させないようにする方法はあるのでしょうか?

コメントも書いていただけるとありがたいです。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:擬似乱数 27082 επιστημη 2006/06/06 23:23:01
<子記事> Re:擬似乱数 27083 def 2006/06/06 23:52:19
<子記事> Re:擬似乱数 27090 もす 2006/06/07 14:04:18
<子記事> Re:擬似乱数 27091 円零 2006/06/07 14:10:41
<子記事> Re:擬似乱数 27098 かずま 2006/06/07 20:08:09


No.27082

Re:擬似乱数
投稿者---επιστημη(2006/06/06 23:23:01)


>普通に0~99の擬似乱数を30個表示しようとすると表示される乱数の値に重複ことがあります。
>
>これを重複させないようにする方法はあるのでしょうか?

int table[100] を用意し、table[i] = i (i=0..99) とします。
つぎにこの内容をデタラメに入れ替えます。
で、table[0]〜table[29] を使います。



この投稿にコメントする

削除パスワード

No.27083

Re:擬似乱数
投稿者---def(2006/06/06 23:52:19)


重複したら、カウントしないでもう一回乱数を生成するという方法が一番簡単かと...
そのためには乱数の内容を記録しておかなければなりませんが、その辺は自分で考えてください。


この投稿にコメントする

削除パスワード

No.27090

Re:擬似乱数
投稿者---もす(2006/06/07 14:04:18)


適当な大きさの配列を用意して
そこに発生させた乱数を入れる

かぶっているものを排除する関数を用意して
それつかえばいいんじゃない?



この投稿にコメントする

削除パスワード

No.27091

Re:擬似乱数
投稿者---円零(2006/06/07 14:10:41)


int stock[100] を用意し、stock[x] = x (x = 0, 1, 2,...99) とします。
i = 99からループを開始するものとして、毎回0〜iまでの乱数を一つ(仮に「n」とします)作ります。
stock[n]を表示します。
stock[n]にstock[i]をコピーします。
iを-1してループします(30回)。

4行目のコピーが鍵です。
例えば、1順目のnが56だったとして、これをしない場合。
2順目において、もはやstock[56]に入っている「56」は選ばれてはいけないのに選ばれ得る範囲に入っており、
一方、まだ選ばれてない「99」がstock[99]に入ったまま選ばれ得る範囲から外れてしまいます。
しかしstock[56]に99を代入すれば、既に使われた「56」は消滅し、まだ使われてない「99」が有効な範囲に入ってきます。
ここで配列stockには「99」が二つあることになりますが、
そのうち一方の「99」はstock[99]に入ったままであり、二度と参照されることがないので問題ありません。


この投稿にコメントする

削除パスワード

No.27094

Re:擬似乱数
投稿者---kz3(2006/06/07 15:39:28)


>int stock[100] を用意し、stock[x] = x (x = 0, 1, 2,...99) とします。
>i = 99からループを開始するものとして、毎回0〜iまでの乱数を一つ(仮に「n」とします)作ります。
>stock[n]を表示します。
>stock[n]にstock[i]をコピーします。

もしこの乱数テーブルを再利用するなら交換がいいですね。
( ってそこまで答えたら考えなくなってしまうか... )

>iを-1してループします(30回)。




この投稿にコメントする

削除パスワード

No.27098

Re:擬似乱数
投稿者---かずま(2006/06/07 20:08:09)


> コメントも書いていただけるとありがたいです。

プログラムを読んで理解することに意味があると思うので、コメントは書きません。
次のプログラムは、わざと分かりにくく書いているので、自分で分かりやすい
形に書き換え、自分でコメントを書いてください。
いくら考えても分からない場合は質問していただければ、できるだけお答えします。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N  100
#define R  30

int rnd[N], n = N;

int get_rnd(void)
{
    int r, t;
    if (n <= 0) return -1;
    r = rand() % n;
    t = rnd[r];
    rnd[r] = rnd[--n] ? rnd[n] : (n + 1);
    return t ? (t - 1) : r;
}

int main(void)
{
    int i;
    srand(time(0));
    for (i = 0; i < R; i++) printf("%d ", get_rnd());
    return 0;
}
このプログラムは、初期化の時間を節約できるように工夫しています。
例えば、0〜9999 の 10000個から 10個の乱数を生成するのに、10000個の
初期化をしなくても良いようになっています。

また、重複したらもう一回乱数を生成するという方法だと、0〜9999 を 10000個
全部出す場合、最後に近づくにつれてやり直しの回数が大きくなり破綻します。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧