正確な乱数を発生するにはどうすれば良いですか

解決


北村 進  2007-03-19 20:38:46  No: 135803

発生の上限をa、下限をrとしました。TextBox1.3に設定した幅と数は合って
いるのに何時も0が最初に出ます。その分乱数が1個足りません。宜しく
お願いします。
    Private Sub Button1_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles Button1.Click
        Dim a As Integer = Val(TextBox1.Text)  
        Dim r As Integer = Val(TextBox3.Text)  
        Dim c, d, j, h, p As Integer    
        Dim b(p) As Integer      
        p = a - r : h = 1      
owari:          
        j = 0        
        d = Int((a - r + 1) * Rnd() + r)    
        For c = 0 To p      
            If b(c) = d Then      
                j = 1      
            End If        
        Next        
        If j = 1 Then      
            GoTo owari      
        ElseIf h <= p Then      
            b(h) = d : h = h + 1 : GoTo owari  
        End If        
        For c = 0 To p      
            TextBox2.Text = TextBox2.Text & b(c) & "  "
        Next        
    End Sub


大吉末吉  2007-03-19 21:25:24  No: 135804

> 何時も0が最初に出ます。
って事ですが・・・

>        p = a - r : h = 1 
>            b(h) = d : h = h + 1 : GoTo owari 

って事は、「hは1以上にしかならない」ので、
「b(0)には、絶対値が入らない」=「初期値の0のまま」
ですよね?


Hongliang  URL  2007-03-19 21:46:30  No: 135805

そもそも、System.Random クラスなら下限と上限を指定して次の整数の擬似乱数を取得するメソッドが使用できます。


よねKEN  URL  2007-03-19 22:22:38  No: 135806

#結論は最初に書くべきですが、あえて考えたことをつらつら書きます。
#とりあえず、結論だけでよい場合は投稿末尾の方をご覧ください。

「正確な乱数を発生する」というタイトルを見てから
質問を読むとちょっと意味がわかりにくかったです。
なぜなら、乱数の値がおかしいということを言われていると思ったので、

  d = Int((a - r + 1) * Rnd() + r) 

に注目しました。
a > rで、r > 0である限り、dが0になることなんてありません!!
「何時も0が最初に出ます。」とありますが、
どうやら変数dのことではないようです。

仕方がないので、プログラムを流し読みすることにしました。
上から順にざーっと見ていきます。
(流し読みしているのでowariラベルには気づきいてませんでした)

GoTo owari

とあるので、owariラベルはきっと最後の方にあるんだろうと思ういつつ、
全体からowariラベルを探したら、始めに・・・。
「始めやんけぇーー!!」と思わず、画面に突っ込みました。

で、この段階で質問内容がわからなくなりました。
そこで直感を働かせながら、さらにプログラムを深く読み進めると
どうやら配列bに重複なく乱数を入れたいのでは?と思えてきました。

結論:
・提示のプログラムのままで行くなら、大吉末吉さんのご指摘の箇所が問題でしょう
・乱数を取得する方法自体は、Hongliangさんも指摘されている
  System.Random クラスを使うのがよいでしょう。
・重複なく乱数を発生させる、という考え方ではなく、
  トランプのカードをシャッフルすることを思い浮かべましょう。
  つまり、rからaまでの値を配列bに順に設定しておき、
  配列bの2要素を交換する作業をたくさん行うということです。
  2要素の位置を決定するときに乱数を使います。


北村 進  2007-03-19 22:33:04  No: 135807

大吉末吉  様
大当たり”一挙解決です。有難うございました。このプログラムはお蔭様で
機能は果たしてはいますが動作がとても遅いです。早くて1分間、遅いと
5分間、場合によっては出るか出ないか心配です。For〜Next と Goto の
二重使用が原因でしょうか。?他によい方法がありましたら教えてください。


大吉末吉  2007-03-19 22:51:20  No: 135808

> 動作がとても遅いです。早くて1分間、遅いと
> 5分間、場合によっては出るか出ないか心配です。

そんなに掛かります?
個数いくつで実行した場合なんでしょうか?

N個の場合の乱数発生回数の「期待値」を計算してみたら、
「(3N-1)/2」回と線形になったので、まあいいかと思ってましたが・・・

既存データの確認ループの方に時間が掛かるのかな・・・
(こちらは2次曲線ですし・・・)
コレを高速化すれば、もうちょっとましかな・・・
#例えば、配列をもう1つ用意して、使った番号にマークするとか・・・

でも、やはり、こういう場合は、よねKENさんが言われているように、

> 重複なく乱数を発生させる、という考え方ではなく、
>   トランプのカードをシャッフルすることを思い浮かべましょう。

こういうやり方が良いでしょうね。


北村 進  2007-03-19 22:53:34  No: 135809

Hongliang 様  よねKEN  様
ご協力下さいまして有難うございました。ご参考にさせていただきます。
これからも宜しくお願い申します。
                                  北村  進


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加