--> -->
#blog2navi() *JavaScriptで本当にランダムな文字列を生成しようとしてみる [#be252cee] JavaScriptでランダムな文字列を生成しようとして検索すると、こういう処理が大量に出てきます。~ #code(php){{ const str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; const len=15; // 文字列長さ let result = ""; for(let i=0;i<len;i++){ result += str.charAt(Math.floor(Math.random() * str.length)); } }} でも、JavaScriptのMath.random()って偏るんじゃないの? とか思って調べてみました。 ** 方法 [#ad949c59] 上記の方法と、[[Fisher–Yatesのシャッフル:https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB]]を使って混ぜて生成した文字列から、各文字の登場回数をカウントしてばらつきを見ます。 ** コード [#la863fe0] 見た方が早いと思います。以下です。 #code(php){{ const len = 8; const str = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; const count = 10000; let good={}; let bad={}; for(let i=0; i<str.length; i++){ good[str.substr(i,1)] = 0; bad[str.substr(i,1)] = 0; } for(let i=0; i<count; i++){ const code = goodCode(len,str); for(let j=0; j<code.length; j++){ good[code.substr(j,1)]++; } } for(let i=0; i<count; i++){ const code = badCode(len,str); for(let j=0; j<code.length; j++){ bad[code.substr(j,1)]++; } } for(let i=0; i<str.length; i++){ console.log(str.substr(i,1)+': good='+good[str.substr(i,1)]+' bad='+bad[str.substr(i,1)]); } function badCode(len,str) { let result = ""; for(let i=0;i<len;i++){ result += str.charAt(Math.floor(Math.random() * str.length)); } return result; } function goodCode(len,str){ return makeRandomArray(str.split('')).join('').substr(0, len); } // 配列をランダムに混ぜる function makeRandomArray(array) { for (let i = array.length - 1; i > 0; i--) { const r = Math.floor(Math.random() * (i + 1)); [array[i], array[r]] = [array[r], array[i]]; } return array; } }} ~2つのランダムな文字列を生成する関数、&inlinecode{goodCode()};と、&inlinecode{badCode()};を作成し、それらを1万回呼んで、生成された8文字の文字列に登場する文字をカウントしています。 ~出力結果は以下の通り。 > 0: good=1299 bad=1316 1: good=1355 bad=1306 2: good=1335 bad=1294 3: good=1248 bad=1264 4: good=1286 bad=1250 5: good=1245 bad=1281 6: good=1287 bad=1290 7: good=1330 bad=1260 8: good=1260 bad=1277 9: good=1377 bad=1269 A: good=1277 bad=1299 B: good=1343 bad=1271 C: good=1267 bad=1264 D: good=1307 bad=1347 E: good=1353 bad=1283 F: good=1231 bad=1317 G: good=1419 bad=1300 H: good=1257 bad=1340 I: good=1314 bad=1315 J: good=1275 bad=1271 K: good=1250 bad=1225 L: good=1317 bad=1226 M: good=1263 bad=1293 N: good=1305 bad=1232 O: good=1290 bad=1326 P: good=1212 bad=1351 Q: good=1264 bad=1230 R: good=1300 bad=1322 S: good=1262 bad=1235 T: good=1244 bad=1359 U: good=1286 bad=1269 V: good=1285 bad=1379 W: good=1271 bad=1318 X: good=1298 bad=1323 Y: good=1241 bad=1315 Z: good=1260 bad=1260 a: good=1332 bad=1246 b: good=1254 bad=1274 c: good=1285 bad=1277 d: good=1335 bad=1306 e: good=1321 bad=1268 f: good=1214 bad=1272 g: good=1284 bad=1300 h: good=1263 bad=1244 i: good=1217 bad=1260 j: good=1272 bad=1406 k: good=1361 bad=1291 l: good=1273 bad=1326 m: good=1275 bad=1314 n: good=1287 bad=1312 o: good=1282 bad=1303 p: good=1317 bad=1293 q: good=1254 bad=1307 r: good=1290 bad=1195 s: good=1315 bad=1268 t: good=1332 bad=1249 u: good=1294 bad=1318 v: good=1303 bad=1269 w: good=1319 bad=1305 x: good=1357 bad=1319 y: good=1280 bad=1311 z: good=1271 bad=1290 < ~これだけだとよく分からないので、散布図にしてみます。 #ref(good.png); #ref(bad.png); ~うーん、バラつき具合は実は変わらない?~ もしかしたらJavaScriptの実装によるのでしょうか・・。 ** 参考 [#jcba2842] -- [[JavaScriptで配列をシャッフルする方法:https://qiita.com/komaji504/items/62a0f8ea43053e90555a]] -- [[Array#sort実装のshuffleは偏る:https://qiita.com/minodisk/items/94b6287468d0e165f6d9]] -- [[JavaScriptでメルセンヌ・ツイスト乱数を使う方法まとめ:https://pisuke-code.com/javascript-how-to-use-mt-rand/]] #htmlinsert(twitterbutton.html) RIGHT:Category: [[[Linux>日記/Category/Linux]]] - 01:05:48 ---- RIGHT:&blog2trackback(); #comment(above) #blog2navi()