• ベストアンサー

サイコロの出る目の確立をプログラムで出すには??

最近VBAの勉強を始めた者です。質問は、タイトルの通りサイコロをn個投げた時の和の合計を求めるプログラムを作りたいのですが、 サイコロの個数n 求める目の和x n個のサイコロを投げた時の目の和Pn(x)とおいて Pn(x)=1/6Pn-1(x-y) y=1,2,3,4,5,6 ここからどのようにプログラムを組んだらよいのかわかないので、もし少しでも分かる方がいらっしゃれば教えていただけませんか?? 宜しくお願いします。

  • ten99
  • お礼率50% (6/12)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

一応数学科にいたことがあるのですが、、、公式を覚えておりません。。。 幼稚っぽい方法ですが、n個のサイコロで期待値xを構成するパターン取得プログラムを書いてみました。 ・コレクション変数に、実現パターンを追加(≪取得_パターン()≫関数) ・コレクション変数へ格納された値を、ファイルに出力(≪結果出力_パターン()≫関数) という方法で行っております。 なので、コレクション変数に収まりきれないような、多いn個のサイコロを指定すると、オーバーフローを起こすと思います。 これを回避するには、全てを溜め込むのではなく、取得したら直ぐにファイルなどに吐き出し、溜め込まないようにしなければなりません。≪結果出力_パターン()≫関数を解析してもらえたら、そのヒントになると思います。 ※探し方のコツ 例1.サイコロがn個(A/B/C・・・n)、合計値4の時 /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* (1)【n個で、4を成立させるパターンを探す】 ○A=1 残りの合計は3 ○A=2 残りの合計は2 ○A=3 残りの合計は1 ▲A=4 残りの合計は0 ×A=5 残りの合計は-1 ×A=6 残りの合計は-2 ・Aの取り得る範囲は 残りのサイコロ(n-1)=0であれば ⇒ 1~4 残りのサイコロ(n-1)>0であれば ⇒ 1~3 (サンプルの≪取得_範囲()≫関数を参照) /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* (2)-1 【A=1を記憶】 (2)-2 【A=2を記憶】 (2)-3 【A=3を記憶】 /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* (2)-1より 【n-1個で、3を成立させるパターンを探す】 ○B=1 残りの合計は2 ○B=2 残りの合計は1 ▲B=3 残りの合計は0 ・・・ ・Bの取り得る範囲は 残りのサイコロ(n-2)=0であれば ⇒ 1~3 残りのサイコロ(n-2)>0であれば ⇒ 1~2 (2)-1-1 【B=1を記憶】 【n-2個で、2を成立させるパターンを探す】 (2)-1-2 【B=2を記憶】 【n-2個で、1を成立させるパターンを探す】 /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* (2)-2より 【n-1個で、2を成立させるパターンを探す】 ○B=1 残りの合計は1 ▲B=2 残りの合計は0 ・・・ ・Bの取り得る範囲は 残りのサイコロ(n-2)=0であれば ⇒ 1~2 残りのサイコロ(n-2)>0であれば ⇒ 1~1 (2)-2-1 【B=1を記憶】 【n-2個で、1を成立させるパターンを探す】 /*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/*/* ・・・・・・・・・・・・・・・・・・・・・・・・・・・ と続きます。。。。。。 パターンは、個数が多いほど樹木のように膨らみますが、A=1としただけで、期待値の範囲は収束していきます。 サンプルでは【「n」個で、「x」を成立させるパターンを探す】という部分を、再帰法を利用し、≪取得_パターン()≫関数としております。 ※このサンプルは、単純な方法を利用しているので、実際には100点の回答ではありません。 例2.サイコロが2個、合計値7の時 「1・6」もあれば「6・1」もあります サンプルは、どちらも同じ様にこのパターンを見つけていますが、重複するパターンは本来探す必要がないはずです。 例3.サイコロが3個(X/Y/Z)、合計値5の時 X≦Y≦Zという仮定をすると 「1・1・3」 「1・2・2」 が得ることができ、あとはこれらの組み合わせで実現します。 以下のサンプルを利用して、文章の意味を理解してもらえたら嬉しいです。 ※準備 >サイコロの個数n シート1のA1に書いて下さい >求める目の和x シート1のB1に書いて下さい ※構成 ・標準モジュール ・クラスモジュール -----標準モジュール(Module1) START----- Option Explicit '取得結果出力ファイル名 Private Const DEF_結果ファイル As String = "c:\Log1.txt" '--------------------------------------------------- 'メイン '--------------------------------------------------- Sub Main()   Const DEF_FSO_書込 As Integer = 2   Dim lng全個数    As Long   Dim lng期待値    As Long   Dim objStrem    As Object   Dim objパターン   As Class1         '----------------------------------------   '//取得メイン部   '----------------------------------------   Set objパターン = New Class1   'シート1番目のセルA1/A2より、パラメータを取得する   lng全個数 = ThisWorkbook.Worksheets(1).Cells(1, 1) 'A1   lng期待値 = ThisWorkbook.Worksheets(1).Cells(1, 2) 'A2      'メイン実行   Call 取得_パターン(lng期待値, lng全個数, objパターン)         '----------------------------------------   '//取得結果出力処理   '----------------------------------------   Set objStrem = CreateObject("Scripting.FileSystemObject").OpenTextFile(DEF_結果ファイル, DEF_FSO_書込, True)   Call 結果出力_パターン(objStrem, objパターン)   objStrem.Close   Set objStrem = Nothing         MsgBox "終了" End Sub '--------------------------------------------------- '取得結果の出力を行う '--------------------------------------------------- Private Function 結果出力_パターン(p_objStrem As Object, p_objパターン As Class1, Optional p_col出力 As Collection) As Boolean   Dim objパターン   As Class1   Dim bln終了フラグ  As Boolean      '出力コレクションが初期化されていなければ初期化を行う   If p_col出力 Is Nothing Then     Set p_col出力 = New Collection   End If      '子供がいなければ終了する   If p_objパターン.c子供.Count = 0 Then     Exit Function   End If      '自分の子供ループ   For Each objパターン In p_objパターン.c子供     '出目を追加する     p_col出力.Add objパターン.c出目          '自分の子供の存在チェック且つ、存在していれば出力対象に追加     bln終了フラグ = Not 結果出力_パターン(p_objStrem, objパターン, p_col出力)          '子供がいない     If bln終了フラグ Then       '出力コレクションをファイルに出力       Call コレクション出力(p_objStrem, p_col出力)     End If          '今追加した子を削除     p_col出力.Remove p_col出力.Count          'もう子がいないのでループ抜け     If bln終了フラグ Then       Exit For     End If        Next objパターン      結果出力_パターン = True End Function '--------------------------------------------------- 'デバッグ用、コレクションのファイルへの出力 '--------------------------------------------------- Private Function コレクション出力(p_objStrem As Object, p_col出力 As Collection)   Dim i    As Integer   Dim strWk  As String   For i = 1 To p_col出力.Count     If (i <> 1) Then       strWk = strWk & vbTab     End If     strWk = strWk & p_col出力.Item(i)   Next i   p_objStrem.WriteLine strWk End Function '--------------------------------------------------- 'サイコロN個による、期待値が出現するパターンを取得する '--------------------------------------------------- Private Function 取得_パターン(ByVal p_lng期待値 As Long, ByVal p_lng全個数 As Long, ByRef p_objパターン As Class1, Optional ByVal p_lng合算値 As Long = 0, Optional ByVal p_lng使用個数 As Long = 1) As Boolean   Dim lng最小値  As Long   Dim lng最大値  As Long   Dim lng出目   As Long   Dim objパターン As Class1      '使用個数とこれまでの合計値を考慮した、最大/最小値を取得する   If Not 取得_範囲((p_lng期待値 - p_lng合算値), p_lng全個数, (p_lng全個数 - p_lng使用個数), lng最小値, lng最大値) Then     Exit Function   End If      '最小~最大値を順にループさせ、次のサイコロを利用し、期待値を絞り込み、パターンを取得する   For lng出目 = lng最小値 To lng最大値     Set objパターン = New Class1     objパターン.c出目 = lng出目          'パターンが取得できたときだけ、パターンを記憶する     If 取得_パターン(p_lng期待値, p_lng全個数, objパターン, (p_lng合算値 + lng出目), (p_lng使用個数 + 1)) Then       p_objパターン.c子供.Add objパターン     End If   Next lng出目      取得_パターン = True End Function '--------------------------------------------------- '期待値に届くための最大値/最小値を求める '--------------------------------------------------- Private Function 取得_範囲( _        ByVal p_lng期待値 As Long _       , ByVal p_lng全個数 As Long _       , ByVal p_lng残個数 As Long _       , Optional ByRef p_lng最小値 As Long _       , Optional ByRef p_lng最大値 As Long _       ) As Boolean      Dim lng最小値 As Long   Dim lng最大値 As Long      Dim lng残最小値 As Long   Dim lng残最大値 As Long         '最小値/最大値を得る   Call 取得_範囲_単純(1, lng最小値, lng最大値)   '残りの個数から可能な最小値/最大値を得る   Call 取得_範囲_単純(p_lng残個数, lng残最小値, lng残最大値)      '適正な範囲の最小値に修正   If ((lng最小値 + lng残最大値) < p_lng期待値) Then     lng最小値 = p_lng期待値 - lng残最大値   End If   '適正な範囲の最大値に修正   If ((lng最大値 + lng残最小値) > p_lng期待値) Then     lng最大値 = p_lng期待値 - lng残最小値   End If      '最大値と最小値が等しく、サイコロを使い切れなかったら抜ける   If (lng最小値 = lng最大値) And (p_lng残個数 <> 0) Then     '異常終了     Exit Function   End If      'パラメータに、取得した最小値/最大値を返却   p_lng最小値 = lng最小値   p_lng最大値 = lng最大値      '正常終了   取得_範囲 = True End Function 'サイコロの個数による、最大値/最小値を求める Private Sub 取得_範囲_単純( _        ByVal p_lng個数 As Long _       , Optional ByRef p_lng最小値 As Long _       , Optional ByRef p_lng最大値 As Long _     )   Const DEF_出目_小  As Long = 1   Const DEF_出目_大  As Long = 6      p_lng最小値 = p_lng個数 * DEF_出目_小   p_lng最大値 = p_lng個数 * DEF_出目_大 End Sub -----標準モジュール(Module1) END----- -----クラスモジュール(Class1) START----- Option Explicit '出目 Public c出目 As Integer '出目に関連する子供たちを記憶する領域 Public c子供 As Collection 'クラス派生時に、記憶領域を初期化 Private Sub Class_Initialize()   Set c子供 = New Collection End Sub -----クラスモジュール(Class1) END-----

ten99
質問者

お礼

大変長い文を書いて説明していただきありがとうございました。

その他の回答 (3)

  • perse
  • ベストアンサー率74% (113/152)
回答No.3

>サイコロを10個投げてその時に目の数の和が100になる確率 をプログラムで求めるには公式がないと無理でしょう。 Pn(x)=1/6Pn-1(x-y)が公式なのでしょうか? だとしたらy(サイコロの目?)の意味がよくわかりません。 (数学には詳しくないので変なこと聞いてたらすいません) もし、プログラムで疑似的に求めたいのなら以下のようになると思います。 '-------------------------ここから Const Times As Long = 100000 Dim lngSai As Long '振るサイコロの個数 Dim lngTotal As Long '求める合計 Dim lngSum As Long Dim lngCnt As Long Dim i As Long, j As Long Randomize 'サイコロの数と求める合計をセット(この値は例) lngSai = 30 lngTotal = 100 For i = 1 To Times lngSum = 0 For j = 1 To lngSai lngSum = lngSum + Int(Rnd() * 6) + 1 Next j '合計が求めたい合計だったらカウント+1 If lngSum = lngTotal Then lngCnt = lngCnt + 1 DoEvents Next i '30(=lngSai)回振って合計が100(=lngTotal)になる確立 MsgBox lngCnt / Times '-------------------------ここまで

ten99
質問者

お礼

分かりやすく説明していただきましてありがとうございました。

  • OsieteG00
  • ベストアンサー率35% (777/2173)
回答No.2

与式の条件がよくわかりません。 xとPn(x)の違いは何でしょう? xはどのように求めたのでしょうか? 単純に サイコロの個数n n個のサイコロを投げた時の目の和P(n) x個目のサイコロの目をf(x)とすると とおいて P(n)=Σ(X=1,n) f(x) ここで f(x)=1~6の間の整数 ではいけないのでしょうか? これで考えると、キーポイントとなるのは ・for~next文による繰り返し ・乱数の発生 ->rnd関数を使用する。rnd関数は0~1の少数の乱数を発生させる関数。乱数の範囲を変えるには、最大値を掛ければよい。整数にしたければ掛けたものをint関数で少数以下の切捨てを。randomize関数を使用すればなおよし(詳細はヘルプを参照)。 <例> 0~3の整数を発生する乱数 int(rnd()*3) <大体の流れ> SumPx=0 for i=1 to n SumPx=SumPx+(乱数) next i

ten99
質問者

補足

早速、回答して頂きありがとうございます。 私の条件式の説明がわかりにくかったみたいで申し訳ないです。 サイコロの個数nと求める目の和xの値は自分で指定して、その場合の確立を求めたいのです。 例えば、サイコロを10個投げてその時に目の数の和が100になる確率は、どのくらいか??っというものを求めようとしています。   

  • parapa
  • ベストアンサー率15% (42/273)
回答No.1

乱数について調べれば 自ずと答えが出ると思いますよ。

ten99
質問者

お礼

回答ありがとうございます。

関連するQ&A

  • サイコロの出る目の確立

    サイコロn個をふった時に例えば10が出る確率はいくらであるか??っていう 確立の出し方をわかる人は居たら教えていただけないでしょうか?? サイコロ2個で10が出る確率のように、サイコロの数が少ない場合はわかるの ですが、サイコロの数が増えると数えるのに膨大な時間がかかるので計算で 出す方法がありました教えてください。よろしくお願いします。

  • サイコロの目の和

    大学時代のノートをめくってたら、自分がギブアップした問題がありました。 分かる方がいたらお教えください。(ノートは正規分布に関するものでした) (問題1) サイコロを7回振って、その目の和が21になる確率は? (問題2) n回目に出たサイコロの目をXnとし、その和をSnとする。 (Sn=X1+X2・・・+Xn) n=100のときに、Sn=mである確率は? (100≦m≦600) ・・・この後、和の分布が正規分布になるような事がノートには 書いてありました。 もう回答を見せるべき相手もいないので、出来なくても平気ですが ちょっと悔しいので、教えてください。

  • さいころの問題

    さいころの和に関する問題です。 n回さいころを振った時、出た目の総和が2nになる確率はどのように求まるのでしょうか。よろしくお願いします。

  • 1つのサイコロを10回投げるとき、3の倍数の目がn

    1つのサイコロを10回投げるとき、3の倍数の目がn回出るときの確率をPnとする。 ( ただし n = 0,1,2,3,・・・・・・10 ) Pnが最大となるときのnの値を求めよ。 ーーーーーーーーーーーーーー という問題が解答を見ても全然分かりません。 詳しく説明出来る方、回答お願い致します。

  • 集合

    サイコロを繰り返しn回振って、出た目のn個の数を掛け合わせた積をXとする。 Xが6で割り切れる確率Pnを求めよ。 解) Pnは「少なくとも一回3か6が出る」かつ「少なくとも一回2か4か6が出る」である これがわかりません。 自分で考えたら、「少なくとも一回3が出る」かつ「少なくとも一回2か4が出る」 または「少なくとも一回6がでる」 となりました。どのようにして解のように考えれるのでしょうか? よろしくお願いします。

  • サイコロの確率

    サイコロを繰り返しn回振って、出た目のn個の数を掛け合わせた積をXとする Xが6で割りきれる確率qnを求めよ 解答は、 少なくとも1回3か6の目が出る事象をA、少なくとも1回2か4か6の目が出るという事象をBとし、qn=1-P(¬(A∩B))を求めてるのですが3や2や4が1回しか出なければ6で割りきれないからA∩Bでは不十分な気がします なぜ不十分ではないのでしょうか?

  • サイコロの問題

    写真のように6つの同じサイコロを互いに接する面の目の数の和がそれぞれ 偶数になるように並べたとき、互いに接しているすべての面の目の数の合計として 正しいのはどれか。ただしサイコロの相対する面の目の数の和は7である。 という問題ですが、右側の3つと左手前はサイコロの目の位置がわかるのですが 左奥の二つは1面しか見えていないのでどう予測をたてるのかがわかりません。 左の真ん中のサイコロを、手前に2を持ってくると(左手前の2と接する面です) 正解の54になるのですが、ここに4を持ってくることも合計は60になりました。 なぜ2と決定することが出来るのでしょうか。 どうぞよろしくお願いします。

  • さいころの目の出方の期待値が全くわかりません。教えてください。

    さいころの目の出方の期待値が全くわかりません。教えてください。 問.1個のさいころを投げて、1の目が出れば100円、2の目が出れば200円をそれぞれ支払い、それ以外のときは150円もらうことにした。このとき、受け取る金額の期待値はいくらか。 回答. 期待値は何がなんだかわかりません。 期待値はこの場合は円が単位ですよね。 どのくらい期待できるかというものを数字に置き換えていると思っていいですか。 または、だいたいこのくらいになるだろうという予想を数値にしていると思うほうですか。 昨日は期待値の定義に当てはめてやりましたが、よくわかりません。 昨日の質問へのお礼と疑問をこれから書き込みます。 早めに問題だけ先に投稿しました。 本に載っている下の定義に沿って教えていただくとありがたいです。 期待値=χ1p1×χ2p2×・・×χnpn ある試行によって定まる値?が幾つかの値をとる・・χ1 χ2・・χn それぞれの値をとる確率が・・・・・・・・・・・ p1 p2・・pn 昨日は p1+p2+・・+pn=1 の条件を書き忘れました。

  • 数学の確率 (さいころ)

    ある確率の問題で 「n個のさいころを同時に投げるとき目の和がn+3になる確率を求めよ」 というものがあるのですが、その答えの式が 6のn乗 分の n H 3(重複組み合わせ   Hのn、3) と書いてありました。 これは分母が、さいころをn個投げる事象の総数の重複順列で、分子はn個から選ぶ 重複組み合わせ となっています。 でも、分母を順列で計算するので分子も順列で考えなくてはならないのではありませんか??どうか分かる方は教えてください。よろしくお願いします。

  • ひとつのサイコロをn回・・・

    (2)の期待値を求めるものが解けません(1)は解けたのですが。 座標平面状の原点から動点P(x,y)がサイコロを投げて1~4ならx方向に+1、5,6ならy方向に+1進みます。 n回投げたとき (1)x-y=k  (-k≦n≦k)である確立は? x方向(→)に進む確立はp=2/3 y方向(↑)に進む確立はq=1/3 ↑…i回、→n-i回すすむとして x-y=i-(n-i)=2i-n=k ∴i=(n+k)/2 よって求める確立Pnは n+kが奇数:Pn=0 n+kが奇数:Pn=n_C_i・p^{i}・q^{n-i}(=Piとおく)(i,p,qを代入) (2)期待値を求める

専門家に質問してみよう