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

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

新規登録して質問してみよう
ただいま回答率
85.54%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

3回答

1066閲覧

乱数の一桁目が1に偏ってしまう

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

1グッド

2クリップ

投稿2023/01/17 23:35

編集2023/01/18 00:14

前提

ここに質問の内容を詳しく書いてください。
乱数の一桁目がどうしても1に偏ってしまいます。

実現したいこと

1に偏らない乱数生成

発生している問題・エラーメッセージ

0.1900724777
0.2039962463
0.775511266
0.979726846
0.1416527678
0.114035211
0.1056855869
0.1825813151
0.1895523205
0.652536334

### 該当のソースコード ```JavaScript function random(){} random.prototype.initRandom = function(s) { this._s = new Array(123456789, 362436069, 521288629, 88675123); for(let i = 0; i < 4; i++) this._s[i] = s = 1812433253 * (s ^ (s >> 30)) + i; }; random.prototype.XorShift = function() { let s = this._s; let t = (s[0] ^ (s[0] << 11)); s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; return (s[3] = (s[3] ^ (s[3] >> 19)) ^ (t ^ (t > 8))); }; random.prototype.seed = function(s) { let int = 0; s = String(s); for(i = 0; i < s.length; i++) { if(i == 0){ int += s.charCodeAt(i); } else { int += s.charCodeAt(i) * 31 ** i; } } if(int > 2 ** 31) { let max = Math.floor(int / 2 ** 31);//2 ^ 31の数 let min = int - max;// int = max + min; } this.initRandom(s); int = Math.abs(this.XorShift()); int = parseFloat("0." + int); return int; }; for(j = 0; j < 10; j++) console.log(new random().seed(j));
miyabi_pudding👍を押しています

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

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

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

tmp

2023/01/18 08:58 編集

蛇足ですが、 このXorShiftは、C言語などからjavascriptへ移植したのでしょうか? C言語だと恐らく整数32bit乗算ですが、式をそのままだと、javscriptのdouble相当の乗算になるので そのまま式をもってきても結果が異なる為、同じシードで初期化してもC言語とjavascirptて異なる結果になります。具体的にはinitRandomの関数の中の、1812433253の数値との乗算で影響。 ほかの影響は、doblue乗算では、下位ビットの情報が失われるので、異なるシードでも同じ疑似乱数がでて来る確率がC言語の時より高くなります。 今回の場合、シード1234567890と同じ疑似乱数のシード 57830248,162653227,236482692,341305671,372299185,415135136,・・まだまだありました。 結構多い?
退会済みユーザー

退会済みユーザー

2023/01/18 14:52

C言語のページから移植したものです。どのようなシードを使うのが正解でしょうか
tmp

2023/01/18 23:23

正しく式を移植ができていないということです。 C言語の32bitの整数同士の乗算は、32bit x 32bit = 64 bitの内下位32bitになりますが 32bit同士の乗算をdoubleで計算すると 32bit相当 x 32bit相当 =52bit の後に下位32bit相当を取得しても、すでに失われた情報は取得できません。 例 javascriptは変数は、通常double相当 123456789*123456789を計算すると15241578750190521ではなく15241578750190520なってしまいます。このあと |0をしても32bitの値は、int同士の乗算と下位32bit同じ値にはなりません。 対処方法の1つは、整数32bit x 32bitを 32bit x下位16bitと32bit x 上位16bitで計算して後で必要な分を加算して取得します。 小学生で習った二桁同士の掛け算を1の位と10の位で別々に計算して加算するのと同じです。 javascriptって、BigIntってあるのですね。これで何でもなんとかなるかも、まだ使ったことないですが・・
退会済みユーザー

退会済みユーザー

2023/01/19 18:30

返答ありがとうございます
guest

回答3

6

0から2^31の乱数だったら最大値は21.5兆ぐらいなので、一様だとしても46.5%ぐらいの確率で10兆台になります。
(10兆未満も46.5%ぐらい、20兆台が7%ぐらい)

また、コードでは別々のシード値の一発目の乱数を左寄せで表示しているので、乱数アルゴリズムの評価方法としてはイマイチな気がします。

js

1 int = String("0." + int);

int = int / 2 ** 31; とすべきなのかもしれません。

投稿2023/01/17 23:54

編集2023/01/18 00:09
int32_t

総合スコア20518

miyabi_pudding, ozwk, yambejp, penguin520, maisumakun👍を押しています

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/01/18 00:11

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

1

この手のアルゴリズムは偏りが発生するのは仕方ありません。
シードを使ったランダムな1未満の数ではなく、mからnまでの整数を返す仕組みにすれば
偏りのある戻り値の剰余を利用して比較的安定した乱数を発生させられます

追記

範囲を指定してランダム数値を生成
以下サンプルは10~99の数値を100個抽出、seed指定なし

javascript

1class Random { 2 constructor(seed = 88675123) { 3 this.x = 123456789; 4 this.y = 362436069; 5 this.z = 521288629; 6 this.w = seed; 7 } 8 next() { 9 let t= this.x ^ (this.x << 11); 10 this.x = this.y; 11 this.y = this.z; 12 this.z = this.w; 13 return this.w = (this.w ^ (this.w >>> 19)) ^ (t ^ (t >>> 8)); 14 } 15 range(min, max) { 16 return min + (Math.abs(this.next()) % (max + 1 - min)); 17 } 18} 19const r= new Random(); 20const datas=[]; 21const min=10; 22const max=99; 23for(let i = 0; i < 100; i++) { 24 datas.push(r.range(min,max)); 25} 26console.log(datas); 27

投稿2023/01/18 00:51

編集2023/01/22 06:07
yambejp

総合スコア114326

退会済みユーザー👍を押しています

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/01/18 00:53

回答ありがとうございます
退会済みユーザー

退会済みユーザー

2023/01/18 00:54

実際にはどういったコードで実装すればよいでしょうか
guest

0

https://teratail.com/questions/emg6q247pyxzan
人の話を聞く気がないのだから何をやっても無駄でしょう。諦めてはいかがですか?
シード値は毎回変えるものでないことも理解せず、
0から1の間の浮動小数点数を得る方法を聞いても無視して、
自己流を続けるのでは、まともに回答をするのがバカらしくなります。

投稿2023/01/21 17:20

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2023/01/21 17:39

退会済みユーザー

退会済みユーザー

2023/01/21 17:47

seed値は毎回変えるものですよ?
ikadzuchi

2023/01/22 15:35

はあ、そうですか。 話を聞く気が無いのは分かりましたし、あなたがどういう認識をしているのかにも興味が無いので、どうぞご自由にシード値を毎回変えてください。 ただ、シード値を毎回変えることによって適切な乱数列が出ないことに疑問を抱くのだけはやめていただけるとありがたいです。
退会済みユーザー

退会済みユーザー

2023/01/23 01:48

実際シード値を毎回変える方法でうまくいっているのですが……
退会済みユーザー

退会済みユーザー

2023/01/23 01:53

自分の認識が誤っていることに気づいたら、ちゃんと謝ってくださいね
ikadzuchi

2023/01/24 00:59

? …ええ、はい。あなたも自分の認識が誤っていることに気づいたら最悪謝らなくてもいいんで報告はあると嬉しいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.54%

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

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

質問する

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。