由于0
不是2的幂,因此随机产生从999999
到1000000
的精确值的正确方法是什么?
这是我的方法:
crypto.randomBytes
生成3个字节并转换为hex
fffff
== 1048575
> 999999
)999999
,请从步骤1重新开始它将以某种方式创建递归函数。它在逻辑上是否正确,是否会引起性能问题?
答案 0 :(得分:5)
有几种方法可以从随机位中提取一定范围内的随机数。 NIST Special Publication 800-90A revision 1: Recommendation for Random Number Generation Using Deterministic Random Bit Generators
中描述了一些常见的尽管此标准是关于确定性随机位生成的,但是有一个有用的附录称为 A.5将随机位转换为随机数,它描述了三种有用的方法。
描述的方法是:
它们中的前两个不是确定性的,但生成的数字完全没有偏差。它们基于拒绝抽样。最后一个是时间常数和确定性的,但具有非零(但可以忽略)的偏差。不过,要实现可忽略的偏差,还需要相对大量的随机性。
您的算法显然是“简单丢弃方法”的一种版本,因此很好。
当然,您应该使用通用方法,该方法在给定N
的情况下都是有效的。在这种情况下,应考虑在简单丢弃方法上考虑复杂丢弃方法或简单模块化方法。还有其他更复杂的算法甚至更有效,但是通常使用这两种方法都可以。
请注意,在生成N
范围内的随机数时,首先检查[0, N)
是否为2的幂通常是有益的。如果N
是2的幂,则无需使用这些可能昂贵的计算中的任何一个;只需使用随机位或字节生成器中所需的位即可。
答案 1 :(得分:4)
这是一种正确的算法(https://en.wikipedia.org/wiki/Rejection_sampling),尽管您可以考虑使用按位运算而不是转换为十六进制。如果随机数生成器发生故障,它可以永远运行-您可以考虑尝试固定次数,然后抛出异常而不是永远循环。
答案 2 :(得分:2)
主要的性能问题是,在某些平台上,crypto.randomBytes
会在熵用尽时阻塞。因此,如果您要使用随机性,就不要浪费它。
因此,我将使用以下整数运算代替您的字符串比较。
if (random_bytes < 16700000) {
return random_bytes = random_bytes - 100000 * Math.floor(random_bytes/100000);
}
从前3个字节中得出答案的机率大约为99.54%,而采用这种方法的几率约为76%。
答案 3 :(得分:0)
我建议采用以下方法:
private generateCode(): string {
let code: string = "";
do {
code += randomBytes(3).readUIntBE(0, 3);
// code += Number.parseInt(randomBytes(3).toString("hex"), 16);
} while (code.length < 6);
return code.slice(0, 6);
}
这将数字代码作为字符串返回,但是如果有必要将其作为数字来获取,则更改为return Number.parseInt(code.slice(0, 6))
答案 4 :(得分:-1)
我称其为random_6d
算法。最坏的情况是只有一个附加循环。
var random_6d = function(n2){
var n1 = crypto.randomBytes(3).readUIntLE(0, 3) >>> 4;
if(n1 < 1000000)
return n1;
if(typeof n2 === 'undefined')
return random_6d(n1);
return Math.abs(n1 - n2);
};
循环版本:
var random_6d = function(){
var n1, n2;
while(true){
n1 = crypto.randomBytes(3).readUIntLE(0, 3) >>> 4;
if(n1 < 1000000)
return n1;
if(typeof n2 === 'undefined')
n2 = n1;
else
return Math.abs(n1 - n2);
};
};
答案 5 :(得分:-1)
这是使用holder.Rank.setText(String.valueOf(currentposition.getRank()));
函数的简单代码。
randomBytes()