まず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 件のコメント:
コメントを投稿