我的字母表中包含 c 字符,并希望使用该字母创建长度 n 的随机String
。
作为一个例子,让我们说字母表由字母a-w
组成(所以 c = 23)和生成的{{1 s的长度应为 n = 67。
生成这样的String
的直观但也很天真的方法可能如下所示:
String
虽然这有效,但我觉得我浪费了太多的熵。在这个例子中,我要求RNG n = 67次为另一个号码,而所有这些只是为了生成一个String alpha = "abcdefghijklmnopqrstuvw";
int c = alpha.length();
int n = 67;
SecureRandom random = new SecureRandom();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < n; i++) {
int nextPosition = random.nextInt(c);
sb.append(alpha.charAt(nextPosition));
}
System.out.println(sb.toString());
。
String
和nextBytes(byte[] bytes)
数组足够大
创建一个长度为67的byte
?String
数组到所需的byte
。如果一个角色有,那将很容易
大小为一个字节(或一个字节的倍数),因此 n = 67 I
可以向RNG询问67个随机String
,然后直接映射
从数组中的每个byte
到一个字符。但是,对于大小为 c = 23的字母,每个字符只有五个字节,甚至没有使用所有五个字节 - 如果我们枚举上面的所有字符,那么第一个字符{{ 1}}的二进制值为byte
,而最后一个字符'a'
的二进制值为00000
(我选择的素数并非巧合)对于 n 和 c ,它确实应该适用于任何情况。)答案 0 :(得分:1)
首先做一些数学运算:我们需要从23个字母的字母表中覆盖67个字符的最小字节数n
是多少?将每个字节视为256个字母的字母表中的“字母”。然后
23 67 &lt; 256 名词
或
n&gt; 67 * ln(23)/ ln(256),可达37.8848或38字节。
你可以生成一个38字节的数组,从中构造BigInteger
,并调用divideAndRemainder(23)
67次以获得单个字符索引和迭代中的下一个数字:
random.nextBytes(bytes);
BigInteger big = new BigInteger(bytes).abs();
BigInteger bigC = BigInteger.valueOf(c);
for (int i = 0 ; i != n ; i++) {
BigInteger[] dr = big.divideAndRemainder(bigC);
res[i] = alpha.charAt(dr[1].intValue());
big = dr[0];
}
String result = new String(res);