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

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

ただいまの
回答率

91.77%

  • アルゴリズム

    251questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

ランダム値の重み付けに指数分布を使いつつ範囲を指定したい

解決済

回答 1

投稿 2016/08/26 16:33

  • 評価
  • クリップ 0
  • VIEW 455

argius

Perl総合1位

言語は問いませんが、コード例としてJavaScriptのものを記載します。

ランダムに0~9の範囲の整数を求めるには、
擬似乱数生成関数の結果(0以上1未満) * (最大値 + 1) ※小数点以下切り捨て
で求めます。

一般的にはこのようなコードになると思います。

var max = 9; // 最大値
var rn = Math.random() * (max + 1); // ランダム値(浮動小数点数)
var result = Math.floor(rn); // 整数(切り捨て)

このランダム値に重みをつけたいです。

試しに、以下のように指数分布を使って求めました。

var lambda = 0.8; // 平均(必ず小数点以下をつける)
var rn = -Math.log(Math.random()) / lambda;
var result = Math.floor(rn);

この場合、指定できるパラメーターは平均で、範囲を決めることができません。
まれに大きな値が返されることがあります。
この結果を、0以上1未満で返すか、または範囲内の整数で返すようにするにはどうしたら良いでしょうか。

そもそも指数分布を使うのが間違いでしょうか?
単純に二次関数などを使って重み付けを行うべきでしょうか?
(二次関数で上手く行くことは確認済みです。)

よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

この場合、指定できるパラメーターは平均で

正確には,「指定できるパラメータは平均の逆数」だと思います.
なので,平均を0.8にしたければ,lambda = 1.0/0.8を指定する必要があります.

ちなみに,平均を0.25くらいにすると,だいたい0 <= P <= 1の範囲に収まります.
が,指数分布を使う限りMath.random()の値が1.0に近いと,結局無限大に近い値になります.

内部で使用する一様分布の範囲を調整して,平均を調整すれば不可能ではありませんが…
(例えば 0 から 0.9 までの一様分布で,平均を 0.43 くらいにする,とか)

投稿 2016/08/26 19:16

編集 2016/08/26 19:21

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

  • 2016/08/26 20:33

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


    ご説明いただいたとおりに、逆数を計算したうえで平均を0.25くらいにすることで
    0 <= P <= 1の範囲が取れるようになりました。


    > 指数分布を使う限りMath.random()の値が1.0に近いと,結局無限大に近い値になります.

    これは一応理解できています。

    検査に使うわけではなく、厳密さはほとんど気にしていません。
    大きい目が出やすいサイコロが欲しい程度のものです。

    そうなると範囲外を捨ててしまうという実装にしてしまっても良いものでしょうか?

    キャンセル

  • 2016/08/26 21:52

    > 指数分布を使う限りMath.random()の値が1.0に近いと

    すみません,この場合「0.0 に近いと」ですね.

    > そうなると範囲外を捨ててしまうという実装にしてしまっても良いものでしょうか?

    どうせ範囲外だとサイコロの目に変換しようがないと思うので,いいんじゃないですかね?
    どちらかというと,「計算結果から範囲外の値を捨てる」というより,「一様乱数の範囲を調整して,指数分布として範囲外の値が出ないようにする」方がスマートな気はしますが.

    キャンセル

  • 2016/08/26 22:06

    横からですが、
    > 大きい目が出やすいサイコロが欲しい程度のもの
    ならば指数分布に拘る必要もないのでは?

    キャンセル

  • 2016/08/26 22:32 編集

    > この場合「0.0 に近いと」ですね

    そうですね。実際、JavaScriptでは乱数が0.0の時はInfinityになりました。

    > 「一様乱数の範囲を調整して,指数分布として範囲外の値が出ないようにする」

    それならできそうです。
    このパラメータでは下限をおよそ0.01832に調整することで、
    0 ≦ P < 1 の範囲で値が出せそうです。

    ありがとうございました!

    キャンセル

  • 2016/08/26 22:32

    ozwkさん

    はい、特にこだわってはいません。
    なにぶん知識不足で、このようなケースではどのような生成関数を使えば良いのか判断が付かなかったので、
    「重み付けでランダム」で調べたところ、指数分布の例(で自分が理解できそうなもの)が比較的多く見つかったんですね。
    それ以外には特に指数分布にする理由はありません。

    キャンセル

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

ただいまの回答率

91.77%

関連した質問

同じタグがついた質問を見る

  • アルゴリズム

    251questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。