まずJavaにはランダムを提供するクラスとして
java.util.Random
java.security.SecureRandom
の2つがあってRandomクラスは以下のような強度しか持っていない。
Random クラスのインスタンスは、一連の擬似乱数を生成します。クラスでは 48 ビットのシードを使い、このシードは線形合同法で変更されます。
no title
しかも初期化があまりよくなくて初回の乱数がとても偏る。
Random r = new java.util.Random();
double x, min = 1, max = 0;
for (int i = 0; i < 1024; i++) {
r.setSeed(i);
x = r.nextDouble();
if (x > max)
max = x;
if (x < min)
min = x;
}
System.out.println("Min=" + min + " Max=" + max);
Min=0.6753377750582709 Max=0.7669794809891215
こんなプログラムを回してみるとと1000通りの種を渡しても初回生成値が極度に偏ってしまう。
んで、SecureRandomはこのあたりの問題を解消するのでててきた。
for (int i = 0; i < 1024; i++) {
sr.setSeed(i);
x = sr.nextDouble();
if (x > max){
max = x;
}
if (x < min){
min = x;
}
}
BigDecimal bigMin = new BigDecimal(min).setScale(16,BigDecimal.ROUND_HALF_UP);
System.out.println("Min=" + bigMin + " Max=" + max);
x = 0.0;
Min=0.0004351500205996 Max=0.9986417236968099
SecureRandomにすると一気に分散するようになった。
ランダムな文字列を生成するには
そもそもランダムな文字列を作る為にRandomを久々にみてたわけですが、
今普通にランダムな文字列を使うのならcommons-langのRandomStringUtilsで事足りる。
アスキー文字なら
RandomStringUtils.randomAscii(10)
⇒DF|M1!7W=@
アルファベットなら
RandomStringUtils.randomAlphabetic(10)
⇒doKntQIMve
数字なら(0始まりも生成されてしまうので注意)
RandomStringUtils.randomNumeric(10)
⇒8266471697
頭0を嫌うなら
RandomStringUtils.random(1,"123456789") + RandomStringUtils.randomNumeric(9);
自分で指定した文字の中からランダムにしたいのなら
RandomStringUtils.random(10,"012345abcdef");
⇒c021cc0b24
長さもランダムにしたいのならRandomUtils.nextIntと組み合わせて(1〜3文字のランダムな文字が変える)
RandomStringUtils.random(RandomUtils.nextInt(3)+1,"12345678");
⇒1
⇒255
⇒86
0 件のコメント:
コメントを投稿