Difference between revisions of "LlFrand/ja"
Mako Nozaki (talk | contribs) m (Undo revision 851502 by Mako Nozaki (Talk)) |
Mako Nozaki (talk | contribs) |
||
Line 7: | Line 7: | ||
|p1_type=float | |p1_type=float | ||
|p1_name=mag | |p1_name=mag | ||
|p1_desc= | |p1_desc=範囲内の任意の float 値 | ||
| | |func_desc=範囲 {{Interval|gte=0.0|lt='''mag'''|lth=mag|center=return}} または {{Interval|lte=0.0|gt='''mag'''|gth=mag|center=return}} の疑似乱数{{Interval/Footnote}} を float で返します。<br/> '''mag''' の符号と同じ符号が復帰値につきます。 | ||
| | |caveats=*この乱数ジェネレータの乱数発生源は無作為ではありません。 | ||
| | **乱数の並びはプロセス全体で共有され、毎回シードを設定するわけではありません。このため、疑似乱数生成は完全に予測可能な、もしくは完全に予測不可能な解を必要とするアプリケーションには適していません。 | ||
|caveats= | *llFrand で任意の {{LSLG/ja|integer}} を '''mag''' に指定すると、暗黙のうちに {{LSLG/ja|float}} に {{LSLG/ja|typecast|型変換}} されることに注意しましょう。整数が {{NoWrap|[-2<sup>23</sup>, +2<sup>23</sup>]}} の範囲外である場合、同等とならない可能性があります (float 型の元々の制約です) 。同じように、 llFrand を使用して乱整数を発生させると、 24 個以上のランダムなビットは含まれません。 | ||
|examples=<lsl> | |examples=<lsl>// コインを投げて、 *だいたい* 五分五分の結果を出します。 | ||
integer coin_toss() | |||
{ | |||
if( llFrand(1.) < .5 ) return TRUE; | |||
return FALSE; | |||
} | |||
// 指定された範囲を超える整数を取得するのに便利なこともあります。 | |||
// スクリプトのグループで果てしない論争を巻き起こしてきた、ものすごくトリッキーで偏向的な方法です。 | |||
// llFrand を使用するときに陥りやすい間違いの主な原因は、範囲の端の bin の大きさが変わってしまうことにあります。 | |||
// | |||
// [0.0,'''mag''') の括弧表記が物語るように、関数は 0.0 を含み、入力された値を含みません。 | |||
// LSL の浮動小数点数は実数のサブセットでしかなく、精度は無限ではないからです。 | |||
// このスキーマでは float t = 1.175494351e-38; より大きな float のジェネレータとしてうまく機能します。 | |||
// この数の場合、関数は 0 を返すことになります。この数より小さい場合、算術エラーが発生します。 | |||
// 乱整数ジェネレータ | |||
// Contributed by Mephistopheles Thalheimer, original function posited by Hg Beeks | |||
// min 以上 max 以下の疑似乱整数を返します。 | |||
// 原理: 範囲を 1.0 に拡張して、最後の bin の間隔が間の bin の間隔と同じになるにします。 | |||
// そして整数を 0 の方向に丸めてキャストします。 | |||
// 注意: この関数は範囲のチェックをせず、 max < min だと落ちます。 | |||
integer random_integer( integer min, integer max ) | |||
{ | |||
return min + (integer)( llFrand( max - min + 1 ) ); | |||
} | |||
default | default | ||
{ | { | ||
touch_start(integer total_number) | touch_start(integer total_number) | ||
{ | { | ||
// | // タッチしたとき、確率 0.5 で "Heads" と言い、 | ||
// そのほかの場合は"Tails"といいます。 | // そのほかの場合は "Tails" といいます。 | ||
if ( | if ( coin_toss() ) | ||
llSay(0, "Heads"); | llSay(0, "Heads"); | ||
else | else | ||
llSay(0, "Tails"); | llSay(0, "Tails"); | ||
integer n1 = random_integer( 2, 8 ); // 2 から 8 の間の乱数を返します | |||
llSay( PUBLIC_CHANNEL, "I chose a " + (string)n1 ); | |||
} | } | ||
}</lsl> | |||
<lsl>// シンプルな乱整数テスター | |||
// Contributed by Mephistopheles Thalheimer | |||
// この乱整数テスターは、乱整数関数でうまく動かないものがある理由を、簡単に見てわかるように説明・証明するために書かれました。 | |||
// 一般的には、どんな乱数ジェネレータでも、パターンが現れたら、関数はランダムでない可能性があるとされます。 | |||
// "silly_random_integer( .. )" で指定されたテストケースでは陥る可能性のある落とし穴を示しています。 | |||
// 一見、いい候補のように見えます。私もそう思っていましたが、実際には、議論する中で、ちょっと考え直してみたところ、 | |||
// 最初と最後の bin は float で取りえる値の半分が整数に丸められたものであることに気がつきました。 | |||
// このため出力は同等でなく、ジェネレータは怪しげであることになります。 | |||
integer random_integer( integer min, integer max ) | |||
{ | |||
return min + (integer)llFrand( max - min + 1 ); | |||
} | |||
integer silly_random_integer( integer min, integer max ) | |||
{ | |||
return min + (integer)( llRound( llFrand( max - min ) ) ); // いいように見えますが、うまくいきません | |||
} | } | ||
</lsl> | |||
|helpers | |||
// シンプルな乱整数テスター | |||
// Contributed by Mephistopheles Thalheimer | |||
list bins; | |||
integer MIN = 2; // 欲しい最小値 | |||
integer MAX = 5; // 欲しい最大値 | |||
integer NUMBER_OF_TRIES = 10000; // 大きければ大きいほどいいですが.. 遅くなります | |||
default | |||
{ | |||
state_entry() | |||
{ | |||
llSay( PUBLIC_CHANNEL, "Bin tester ready."); | |||
bins = []; | |||
} | |||
touch_start(integer total_number) | |||
{ | |||
llSay( PUBLIC_CHANNEL, "Started, be patient" ); | |||
integer i; | |||
integer r; | |||
integer range = MAX - MIN; | |||
for( i = 0; i <= range; ++i ) | |||
{ | |||
bins += [ 0 ]; | |||
} | |||
integer v; | |||
integer out_of_range; | |||
for( i = 0; i < NUMBER_OF_TRIES; ++i ) | |||
{ | |||
r = silly_random_integer( MIN, MAX ); // これをテスト対象の関数に置き換えてください | |||
// この結果は約 0.5 の確率で bin の最初と最後にヒットします。 | |||
//r = random_integer( MIN, MAX ); | |||
if( r > MAX || r < MIN ) | |||
{ | |||
out_of_range++; | |||
} | |||
else | |||
{ | |||
v = llList2Integer( bins, r - MIN ); | |||
bins = llListReplaceList( bins, [ ++v ], r - MIN, r - MIN ); | |||
} | |||
} | |||
for( i = 0; i <= range; ++i ) | |||
{ | |||
llOwnerSay( "Bin #" + (string)( i + MIN ) + " = " + (string)llList2Integer( bins, i ) ); | |||
} | |||
llOwnerSay( "Number out of range = " + (string)out_of_range ); | |||
} | |||
}</lsl> | |||
|helpers=[[Pseudo-random_Number_Generator]] - ランダムに見える解を繰り返し必要とするアプリケーションに適しています。 | |||
|also_header | |also_header | ||
|also_functions | |also_functions={{LSL DefineRow||{{LSLG/ja|llListRandomize}}|}} | ||
|also_tests | |also_tests | ||
|also_articles | |also_articles | ||
|also_footer | |also_footer | ||
|notes | |notes | ||
|cat1=Math | |cat1=Math | ||
|cat2 | |cat2 | ||
|cat3 | |cat3 | ||
}} | }} |
Revision as of 22:03, 15 May 2010
LSL ポータル | 関数 | イベント | 型 | 演算子 | 定数 | 実行制御 | スクリプトライブラリ | カテゴリ別スクリプトライブラリ | チュートリアル |
警告
- この乱数ジェネレータの乱数発生源は無作為ではありません。
- 乱数の並びはプロセス全体で共有され、毎回シードを設定するわけではありません。このため、疑似乱数生成は完全に予測可能な、もしくは完全に予測不可能な解を必要とするアプリケーションには適していません。
- llFrand で任意の integer を mag に指定すると、暗黙のうちに float に 型変換 されることに注意しましょう。整数が [-223, +223] の範囲外である場合、同等とならない可能性があります (float 型の元々の制約です) 。同じように、 llFrand を使用して乱整数を発生させると、 24 個以上のランダムなビットは含まれません。
サンプル
<lsl>// コインを投げて、 *だいたい* 五分五分の結果を出します。
integer coin_toss() {
if( llFrand(1.) < .5 ) return TRUE; return FALSE;
}
// 指定された範囲を超える整数を取得するのに便利なこともあります。 // スクリプトのグループで果てしない論争を巻き起こしてきた、ものすごくトリッキーで偏向的な方法です。 // llFrand を使用するときに陥りやすい間違いの主な原因は、範囲の端の bin の大きさが変わってしまうことにあります。 // // [0.0,mag) の括弧表記が物語るように、関数は 0.0 を含み、入力された値を含みません。 // LSL の浮動小数点数は実数のサブセットでしかなく、精度は無限ではないからです。 // このスキーマでは float t = 1.175494351e-38; より大きな float のジェネレータとしてうまく機能します。 // この数の場合、関数は 0 を返すことになります。この数より小さい場合、算術エラーが発生します。
// 乱整数ジェネレータ // Contributed by Mephistopheles Thalheimer, original function posited by Hg Beeks
// min 以上 max 以下の疑似乱整数を返します。
// 原理: 範囲を 1.0 に拡張して、最後の bin の間隔が間の bin の間隔と同じになるにします。 // そして整数を 0 の方向に丸めてキャストします。
// 注意: この関数は範囲のチェックをせず、 max < min だと落ちます。
integer random_integer( integer min, integer max ) {
return min + (integer)( llFrand( max - min + 1 ) );
}
default {
touch_start(integer total_number) { // タッチしたとき、確率 0.5 で "Heads" と言い、 // そのほかの場合は "Tails" といいます。 if ( coin_toss() ) llSay(0, "Heads"); else llSay(0, "Tails"); integer n1 = random_integer( 2, 8 ); // 2 から 8 の間の乱数を返します llSay( PUBLIC_CHANNEL, "I chose a " + (string)n1 ); }
}</lsl>
<lsl>// シンプルな乱整数テスター // Contributed by Mephistopheles Thalheimer
// この乱整数テスターは、乱整数関数でうまく動かないものがある理由を、簡単に見てわかるように説明・証明するために書かれました。 // 一般的には、どんな乱数ジェネレータでも、パターンが現れたら、関数はランダムでない可能性があるとされます。
// "silly_random_integer( .. )" で指定されたテストケースでは陥る可能性のある落とし穴を示しています。 // 一見、いい候補のように見えます。私もそう思っていましたが、実際には、議論する中で、ちょっと考え直してみたところ、 // 最初と最後の bin は float で取りえる値の半分が整数に丸められたものであることに気がつきました。 // このため出力は同等でなく、ジェネレータは怪しげであることになります。
integer random_integer( integer min, integer max )
{
return min + (integer)llFrand( max - min + 1 );
}
integer silly_random_integer( integer min, integer max ) {
return min + (integer)( llRound( llFrand( max - min ) ) ); // いいように見えますが、うまくいきません
}
// シンプルな乱整数テスター
// Contributed by Mephistopheles Thalheimer
list bins;
integer MIN = 2; // 欲しい最小値 integer MAX = 5; // 欲しい最大値
integer NUMBER_OF_TRIES = 10000; // 大きければ大きいほどいいですが.. 遅くなります
default {
state_entry() { llSay( PUBLIC_CHANNEL, "Bin tester ready."); bins = []; }
touch_start(integer total_number) { llSay( PUBLIC_CHANNEL, "Started, be patient" ); integer i; integer r; integer range = MAX - MIN; for( i = 0; i <= range; ++i ) { bins += [ 0 ]; } integer v; integer out_of_range; for( i = 0; i < NUMBER_OF_TRIES; ++i ) { r = silly_random_integer( MIN, MAX ); // これをテスト対象の関数に置き換えてください // この結果は約 0.5 の確率で bin の最初と最後にヒットします。 //r = random_integer( MIN, MAX );if( r > MAX
便利なスニペット
Pseudo-random_Number_Generator - ランダムに見える解を繰り返し必要とするアプリケーションに適しています。
関連項目
関数
• | llListRandomize |