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

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

新規登録して質問してみよう
ただいま回答率
86.12%
アルゴリズム

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

解決済

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

argius
argius

総合スコア9382

アルゴリズム

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

1回答

0グッド

0クリップ

2779閲覧

投稿2016/08/26 07:33

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

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

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

lang

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

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

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

lang

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

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

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

よろしくお願いします。

以下のような質問にはグッドを送りましょう

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

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

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

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 10:16

編集2016/08/26 10:21
tamy

総合スコア442

argius👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

argius

2016/08/26 11:33

回答ありがとうございます! ご説明いただいたとおりに、逆数を計算したうえで平均を0.25くらいにすることで 0 <= P <= 1の範囲が取れるようになりました。 > 指数分布を使う限りMath.random()の値が1.0に近いと,結局無限大に近い値になります. これは一応理解できています。 検査に使うわけではなく、厳密さはほとんど気にしていません。 大きい目が出やすいサイコロが欲しい程度のものです。 そうなると範囲外を捨ててしまうという実装にしてしまっても良いものでしょうか?
tamy

2016/08/26 12:52

> 指数分布を使う限りMath.random()の値が1.0に近いと すみません,この場合「0.0 に近いと」ですね. > そうなると範囲外を捨ててしまうという実装にしてしまっても良いものでしょうか? どうせ範囲外だとサイコロの目に変換しようがないと思うので,いいんじゃないですかね? どちらかというと,「計算結果から範囲外の値を捨てる」というより,「一様乱数の範囲を調整して,指数分布として範囲外の値が出ないようにする」方がスマートな気はしますが.
ozwk

2016/08/26 13:06

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

2016/08/26 13:32 編集

> この場合「0.0 に近いと」ですね そうですね。実際、JavaScriptでは乱数が0.0の時はInfinityになりました。 > 「一様乱数の範囲を調整して,指数分布として範囲外の値が出ないようにする」 それならできそうです。 このパラメータでは下限をおよそ0.01832に調整することで、 0 ≦ P < 1 の範囲で値が出せそうです。 ありがとうございました!
argius

2016/08/26 13:32

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

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

ただいまの回答率
86.12%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

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

アルゴリズム

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