他の質問での回答に対してもう少し具体的に知りたいと思って投稿しました。
自分はいわゆる日曜プログラマです。
勉強のつもりでOKWebのコンピュータ関連でいろいろ回答してます。
(未熟者なのでとんちんかんなのが多いですが)
で次の質問に回答しました。内容は「重複しない乱数を発生させる方法」です。
http://okweb.jp/kotaeru.php3?q=1239644
私が回答したのは#10です。私の考えは
1. 最初に配列に重複しない値を入れ(1から100を順番に)
2. 2要素の値を入れ換える
3. 2を任意の回数繰り返す
4. 配列の先頭から値を取り出す
という考えです。
が、そのあと#12の回答があり、それを読むと私の方法ではマズイようです。
「どうしてマズイのか」ということはなんとなくわかった(ような)気がするんですが、
では「具体的にどうすべきなのか」が知りたいです。
違う方法として自分ではこう考えました。
上記1の配列(これを配列Aとする)と同じ要素数(ここでは100個)の配列Bを作って
1. 0~(配列Aの要素数 - 1)の範囲で乱数を発生させる -> 得られた数値をnとする
2. 配列A[n]の値を配列Bに入れる -> 最初は配列B[0]に入れる
3. 配列A[n]を削除 -> 要素数が1個減る
以下これを繰り返し、配列B[99]まで入れて終了。
過去の質問を覗いてみましたが、いろいろな方法があってどれがいいのか迷ってきま
した。どちらかというと具体的なソースではなく考え方を教えてください。
よろしくお願いします。
No.8ベストアンサー
- 回答日時:
>元の質問のリンク先にある「9通り」「6通り」の意味がどうもよく分かりません。
すでに、ちゃんとした回答がなされているので、特に言うことはないのですが、もとの質問での私の回答で、「均等な乱数が得られない。」というのが、ちょっと語弊があったと思います。すみません。
ここで、他の方の回答にもあるように、交換した結果のパターンの出現確率が一様にならないという意味です。
9通り、6通りというのは、
ある手順で起こりうる全事象の数が9であり
結果として起こりうる全事象の数が6である
ということで、
少なくとも、ある手順の結果起こりうる事象の数はこの場合6の倍数になっていなくてはなりません。
本当にどのような並びになっているかどうか調べるまでもなく、均等な出現にならないと判断できるということです。
つまり、9通り×9通り×…という手順を繰り返す方法では、6の倍数にならないので、結果としてできる出現パターンは均等になりません。
あと、
ABCを交換の結果ABCになったからといって、交換がなかったのと同じであるから無視して良いとはならないと思います。
もうすでに他の方が書かれているので、繰りかえしは避けますが、3つの様な、少ない要素数の場合は、交換の結果の(一回の手順での)出現パターンは、全部列挙して調べることができます。
ABCから任意の2つを交換して得られるパターン
ABC:3回
ACB:2回
BAC:2回
BCA:0回
CAB:2回
CBA:0回
全9通り
理想の場合は、これが各1回になって欲しいワケです。
このように、要素が少ない時、手順の回数が少ない時は、容易に調べられますが、そうでない時には、簡単には調べられません。
なので、9通り、6通りというのは、簡易に判別できる考えだと思います。
この回答への補足
PLUEPIXYさんの回答はいつも「的確だなー。すごいなー」と思って読ませて
いただいてます。今回は私の誤りに気づかせていただいてたいへん感謝して
おります。
実は向こうの質問でお聞きしようとも思ったのですが、質問者ではないのに
あまりかき回すのはよくないかなと思い、質問を立ち上げた次第です。
もし、BLUEPIXYさんに余計なお手間を取らせたとしたら申し訳ございません。
ひとえに私の理解力のなさが原因です。お許しください。
お礼が遅くなってすみません。
BLUEPIXYさんはこの質問のきっかけになった方なので、御本人から回答いた
だけてたいへん嬉しいです。ありがとうございました。
おかげで疑問がとけました。
No.11
- 回答日時:
#3 です。
質問文を読み返すと、質問された方が書かれているアイディアは、#1の方と、考え方としては同じであることに気づき、私の説明は蛇足であったと思いました。問題文を注意深く読まず失礼しました。
#7 の方が計算されているのですが、「入れ替え法」は、N個の要素があるとき、N!の状態(並び方)を遷移する Markov Chain という確率過程ではないでしょうか(参考URL)。各状態からの遷移確率が「同じように」なっているので、収束する際には、ある状態(並び方)にある確率が同じになるはずでは、と考えました。
既出ですが、「入れ替え法」では最低N-1回の入れ替えをしないことにはたどり着けない並び方があるように思います(要素が一個づつずれたような並び方)。
参考URL:http://www.staff.city.ac.uk/r.j.gerrard/courses/ …
参考URLありがとうございました。
正直、数学の知識がない上に、英語のページなので私には難しすぎるのです
が、できることからぼちぼち勉強します。道は険しいですが...。
No.10
- 回答日時:
#7です。
勘違いして申し訳ありません。入れ替え法の場合、交換の相手が自分自身であることを許容すると交換が奇数回か偶数回に関係なく等確率に収束します。
計算例を示します。
(1,2,3)から出発して (3,1,2)ができる各回の確率
0, 0.88888/6, 0.88888/6, 0.98765/6, 0.98765/6, 0.99863/6, 0.99863/6, ・・・
このあとは、2回ごとに 1/6 との誤差が 1/9倍になります。
(1,2,3,4)から出発して (4,1,2,3)ができる確率
0, 0, 0.75/24, 0.75/24, 0.9375/24, 0.9375/24, 0.984375/24, 0.984375/24, ・・・
このあとは、2回ごとに 1/24 との誤差が 1/4倍になります。
どうやら、確率の不均等は指数関数的に減少するようですが、証明があるかどうかはわかりません。
学校で数学を勉強したのはもう20年以上前なので、正直、確率とかの話にな
ると「遠い昔の思い出」って感じです。
いくつになっても勉強だなー、と痛感いたします。
No.9
- 回答日時:
誤解があるといけないので、補足。
shkwta さんのおっしゃる偶置換・奇置換の話は、私や BLUEPIXY さんが考えている入れ替えとは前提条件が違います。
私や BLUEPIXY の話に出てくる入れ替えには「同じ数同士を入れ替える」つまり「実質的には入れ替えないのと同じ」パターンが含まれているのに対し、shkwta さんの話ではこのパターンを含みません。
例えば、同じ数同士を入れ替えるパターンを含む入れ替えを考える場合に、偶置換・奇置換の違いを考えるのは意味がないということです。(前提条件がごっちゃになっている)
以上、文面から誤解する人がいるかもしれないと思ったのでちょっと補足しました。
たびたびありがとうございます。なにしろ自分で判断できるほどの理解力が
ないので、丁寧に説明していただくのはとてもうれしいです。
貴重なお時間を割いていただいてありがとうございました。
No.7
- 回答日時:
入れ替え法について補足します。
有限回の入れ替えでは、すべての順列が厳密には等確率にはなりませんが、回数を多くすると限りなく等確率に近づきます。しかし、各入れ替えごとに、順列のうち半分しか実現しないことに注意が必要です。
たとえば、(1,2,3)の入れ換えですと、奇数回の入れ替えでは(1,3,2) (2,1,3) (3,2,1)の3つだけが実現し、偶数回の入れ替えでは(2,3,1) (3,1,2) (1,2,3) の3つだけが実現します。前者を奇置換、後者を偶置換といいます。
したがって、入れ換え回数を偶数にするか奇数にするかというところも乱数で決めないと、全部の順列に行き渡らないことになります。
No.4の方の質問ですが、(1,2,3)を2回入れ替える方法は9通りあります。9通りの中に(2,3,1) (3,1,2) (1,2,3) の3つの偶置換が3つずつ入っています。この場合はたまたま等確率ですが、(1,2,3,4)と要素を4つにすると入れ替えでは等確率にはなりません。
奇置換、偶置換という言葉を初めて知りました。勉強になります。
いろいろ方法があるもんですね。一人で考えてると方法が偏ってしまって。
ありがとうございました。
No.6
- 回答日時:
「ランダムに選んだ二つの数を入れ替える」を何度も繰り返す方法 (前の質問の masa_pee さんの方法) がいけないのは、100% ランダムなシャッフルができない、という点です。
値の入れ替えを何度繰り返せば 100% ランダムにシャッフルできたと言えるでしょうか?
2回や3回ではもちろん駄目ですよね。選ばれない数 (入れ替えをしない数) がまだたくさんあります。
100 個の数の配列に対し 100 回入れ替えを行っても、まだちょっと不安ですよね。乱数の偏りによって、選ばれない数がいくつかあるかもしれない。では 300 回ならどうか? ほとんど問題ないと思いますが、数学的にはまだ完全に 100% だとは言えません。
100% ランダムにシャッフルするには、無限回の入れ替えをする必要があるのです。
ポイントは、乱数の偏りによって選ばれない数があるかもしれない、という点です。100% ランダムにシャッフルするには、全ての数を同じ割合で選んでゆく必要があります。
そして、masa_pee さんが今回の質問文に書いた方法や、cyoki_par さんの回答文にある方法が、まさにその 100% ランダムにシャッフルできる方法なのです。
前の質問で BLUEPIXY さんがおっしゃっている「交換の結果は均等な結果にならない」ことですが、三つの数のうち二つをランダムに一回入れ替えるという例で考えてみます。
三つの数をランダムに並べた結果は 6 通りあります。
[123][132][213][231][312][321]
これら 6 通りから、それぞれ 1/6 の確率でどれか一つを選ぶのが、100%ランダムなシャッフルですね。
しかし、[123]という配列をあらかじめ用意しておいて、ランダムに選んだ二つの数を 1 回入れ替える、という操作を行ったとき、結果は等確率にはならないのです。
ランダムに選んだ二つの数が同じだった場合――実質的には入れ替えないのと同じ――の確率は 1/3 になります。しかし、本当にランダムなシャッフルなら確率は (上に書いたように) 1/6 になるはずです。
つまり、この方法では [123] は他のものよりも出やすいのです。逆に、[312] あるいは [231] になる確率は 0 です。
もちろん、何度も何度も入れ替えれば確率は均等になってゆきますが、(無限回入れ替えない限り) きっかり 1/6 にはなりません。等確率ではない入れ替えを何度行っても、結果はやはり等確率にはならないのです。
この回答への補足
お礼を下書きから写したときに余分なものが入ってしまいました。
> #6
なんかこれじゃ#6さんを呼び捨てにしてるみたいで。単なる間違いですので。
#6
回答ありがとうございます。
> 値の入れ替えを何度繰り返せば ...
今回の件に限らず、「とりあえずできる」けど「本当にそれでいいのか」でよく悩みます。
こういうときに気軽に訊ける人がいればいいんですがね。
No.5
- 回答日時:
重複しない乱数を発生させる方法としては、No.2の方の方法が一番オーソドックスです。
無駄な試行も無いですしロジックも比較的簡単です。
私もよく使っています。
前回の質問のNo.12の方の指摘は無視して結構です。
9通りのうち、自分自身を入れ替える3通りを除けばちゃんと6通りになりますし、
乱数としておかしくなる要素は全く有りません。
ただ、害は無いですが、自分自身を入れ替えるのは無駄ですね。
それと最後に余分な話ですが、重複の無い乱数と言うのは本当の乱数ではありません。
本当の乱数なら同じ数字が続く事もあるのです。
重複がないと言うことは単なる「シャッフル」ということで擬似乱数ですね。
最後の「余分な話」ですが、余分ではなく、大変ためになります。
経験者の方の御意見はたいへん参考になります。
ありがとうございました。
No.4
- 回答日時:
質問読みましたが、No.1およびNo.3に同意です。
元の質問のリンク先にある「9通り」「6通り」の意味がどうもよく分かりません。
あと「乱数」と「順番入れ替え」を整理して考える必要があると思います。
そもそも交換による「順番入れ替え」法は、トランプなどの「シャッフル」をプログラム上で実現させるためのアルゴリズムであって、乱数を発生させる方法ではないです。
「シャッフル」はカードを配り終えたときに、すべてのカードが均等に1回ずつ出現することが保証されなければなりませんが、「乱数」ではそのような保証はありません。というか、保証がある時点で「乱れた」数ではなくなってしまいます。
回答ありがとうございます。
> あと「乱数」と「順番入れ替え」を整理して考える必要があると思います。
うーん、こういうところのあいまいさが間違いの原因なんでしょうね。
No.3
- 回答日時:
私もNo.1(No.2)の方が書かれた方法がよいのでは、と考えています。
というのも、これは例えば、0から99までの数字がそれぞれ書いてある100個のボールを、袋から「ランダム」に一つずつ(取ったボールは袋に戻さずに)100回取り出すことと同じ効果があると思えるからです。ところで便乗質問なのですが、質問された方が以前投稿された回答(No.10)で、任意の2数を交換する手続きの回数が「十分大きい」場合、はじめの数字の並べ方の順番の影響が少なくなり、結果として得られる数列を「ランダム」といってもさしつかえなくなるのではないでしょうか? また、No.12の方が書かれている「9通り...6通り...」ということが、「ランダム」でない説明としてどのように関係しているのかわからないので、補足してくださる方がいれば幸いです。
いずれにしても、以下のNo.1の方が書かれた方法だと、手続きが(「十分に大きな回数」ではなく)100回で終わるので、やはりこの方法が効率的でよいかと私は思います。
ありがとうございます。
OKWebを読んでると「こうすればできるよ」という回答はよく目に付くんですが、
あと一歩「どうしてこうするのか」が知りたいことがあるんですよね。
No.2
- 回答日時:
前の私の回答は正確ではなさそうですので補足を。
0~Nの乱数を発生させてBが得られたら、A(B)の内容とA(N)の内容を交換します。
それからNを一つ減らす。
A(99)、A(98)、A(97)の順に発生した乱数を保存されるようになります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- Java javaでのプログラム(配列)について質問です. 2 2022/10/14 22:27
- Visual Basic(VBA) VBAで大量データの処理 3 2022/11/15 21:53
- Perl perlで2次元配列をサブルーチンに値渡しで渡す 5 2022/12/17 18:49
- Excel(エクセル) ExcelVBAでリストの項目に必要数と同じ手配数を分配していくマクロを作りたいです。 1 2022/07/29 18:36
- Ruby 初心者プログラミング 3 2022/10/12 11:31
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- Excel(エクセル) エクセルでエラーを無視して一番左側のセルの値を返したい 2 2023/07/27 13:06
- Java Java 南京錠 2 2023/02/04 11:46
- PHP 配列の値の更新方法について 1 2022/08/05 09:49
このQ&Aを見た人はこんなQ&Aも見ています
-
好きなおでんの具材ドラフト会議しましょう
肌寒くなってきて、温かい食べ物がおいしい季節になってきましたね。 みなさんはおでんの具材でひとつ選ぶなら何にしますか? 1番好きなおでんの具材を教えてください。
-
あなたにとってのゴールデンタイムはいつですか?
一週間の中でもっともテンションが上がる「ゴールデンタイム」はいつですか? その逆で、一週間でもっとも落ち込むタイミングでも構いません。 よかったら教えて下さい!
-
これ何て呼びますか Part2
あなたのお住いの地域で、これ、何て呼びますか?
-
この人頭いいなと思ったエピソード
一緒にいたときに「この人頭いいな」と思ったエピソードを教えてください
-
14歳の自分に衝撃の事実を告げてください
タイムマシンで14歳の自分のところに現れた未来のあなた。 衝撃的な事実を告げて自分に驚かせるとしたら何を告げますか?
-
Processingについて
その他(パソコン・スマホ・電化製品)
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~11/22】このサンタクロースは偽物だと気付いた理由とは?
- ・お風呂の温度、何℃にしてますか?
- ・とっておきの「まかない飯」を教えて下さい!
- ・2024年のうちにやっておきたいこと、ここで宣言しませんか?
- ・いけず言葉しりとり
- ・土曜の昼、学校帰りの昼メシの思い出
- ・忘れられない激○○料理
- ・あなたにとってのゴールデンタイムはいつですか?
- ・とっておきの「夜食」教えて下さい
- ・これまでで一番「情けなかったとき」はいつですか?
- ・プリン+醤油=ウニみたいな組み合わせメニューを教えて!
- ・タイムマシーンがあったら、過去と未来どちらに行く?
- ・遅刻の「言い訳」選手権
- ・好きな和訳タイトルを教えてください
- ・うちのカレーにはこれが入ってる!って食材ありますか?
- ・おすすめのモーニング・朝食メニューを教えて!
- ・「覚え間違い」を教えてください!
- ・とっておきの手土産を教えて
- ・「平成」を感じるもの
- ・秘密基地、どこに作った?
- ・【お題】NEW演歌
- ・カンパ〜イ!←最初の1杯目、なに頼む?
- ・一回も披露したことのない豆知識
- ・これ何て呼びますか
- ・初めて自分の家と他人の家が違う、と意識した時
- ・「これはヤバかったな」という遅刻エピソード
- ・これ何て呼びますか Part2
- ・許せない心理テスト
- ・この人頭いいなと思ったエピソード
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・好きなおでんの具材ドラフト会議しましょう
- ・餃子を食べるとき、何をつけますか?
- ・あなたの「必」の書き順を教えてください
- ・ギリギリ行けるお一人様のライン
- ・10代と話して驚いたこと
- ・大人になっても苦手な食べ物、ありますか?
- ・14歳の自分に衝撃の事実を告げてください
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
pythonについて
-
アセンブラーの命令についてです。
-
添付URLの様な3Dが動くWEBサイ...
-
vba クリップボードクリアにつ...
-
添付URLの様なサイトを作るには...
-
Google ColaboでGUI作成
-
Rでのデータフレーム作成について
-
PythonのTkinter詳しい方へ。画...
-
Pythonのエラーメッセージをコ...
-
正規表現
-
Pythonのスクレイピングの質問...
-
JRのjsonファイルって使って大...
-
google Colabでmatplotlibの描...
-
Python... 環境設定 初心者です...
-
Google Colabでimport soxが出...
-
フロントエンドエンジニアをし...
-
アセンブリ言語について。
-
プログラミングのやり方ざっく...
-
fortran write文について マチ...
-
テキストファイルの1行目のみを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
配列の要素番号を取得するには?
-
VBでボタンを押すと画像をラン...
-
変な質問ですみません、n番目の...
-
VB.NET の配列の要素数
-
重複しない乱数の生成
-
DataGridでCTRLキーを押さずに...
-
Vba 配列の中の特定文字列の位...
-
VB6 複数行のテキストをリスト...
-
データ構造のテキスト保存につ...
-
重複しない乱数を作り配列に入...
-
複数の変数宣言を、for文で一気...
-
FlashソフトSuzukaで、トランプ...
-
ランダムで画像を表示させるには?
-
FLASHでXMLを読み込んだときに...
-
画面上にランダムでムービーク...
-
確率を設定したい
-
ランダム表示を重複させないよ...
-
Adobe FlashCS3【ActionScript3...
-
IDの自動採番について
-
文章の改行数を取得する
おすすめ情報