假设我有
是否存在一种数学方法来获取由种子确定的[1, 20]
范围内的随机数?
即
rand(seed int, range [int, int]);
rand(1, [1, 20]); // "4"
rand(1, [1, 20]); // "4" (if seed and range is the same, I expect the same value)
rand(1, [1, 21]); // "6" (changing range changes random number)
rand(2, [1, 20]); // "9" (changing seed changes random number)
答案 0 :(得分:1)
结果是,我一直在寻找所谓的伪随机数生成器(PRNG)。
有许多PRNG实现。 Mersenne Twister最受欢迎,但安全性也很弱。
我和https://www.npmjs.com/package/seeded-rand一起去了
const SEED = 123,
const LOWER_RANGE = 1;
const UPPER_RANGE = 100;
const srand = new Srand(SEED_ID);
const gifId = srand.intInRange(LOWER_RANGE, UPPER_RANGE);
这将提供1到100之间的确定性数字,即,多个程序执行将在给定相同种子的情况下返回相同数字。
结果是我最初的尝试并不像我想象的那样随机。
https://github.com/DomenicoDeFelice/jsrand/issues/3
解决方案是先对种子进行哈希处理,例如
import {
createHash,
} from 'crypto';
import Srand from 'seeded-rand';
const seed = createHash('sha1').update(String(SEED)).digest().readUInt32BE();
new Srand(seed).intInRange(1, UPPER_RANGE);
如果每个种子仅需要1个确定的随机值,则这里根本不需要随机函数。只需seed % UPPER_RANGE
(见下文)即可。
许多PRNG允许您指定输出范围。如果不是,则通常为0(含)到1(不含),基本上就足够了:
let range = (max - min);
Math.floor(value * range) + min
如果您采用的是这种方法,请确保仔细检查所选的实现是否不包含1(包括1),因为那样的话,它有时会超出最大值。
此外,如果您对可识别的可预测性模式还可以,那么您可以使用SEED % UPPER_RANGE
,即
123 % 20; // "3"
124 % 20; // "4"
// ...
164 % 20; // "4"
感谢Freenode的 joepie91 的指导。我只是在记录他的建议。
答案 1 :(得分:0)
我写了一个概念,说明如何使用简单的数学和循环来做到这一点。我相信细节可以改善,但是总的来说,您是否想要这样的东西?
// Seed random (pseudo-random)
const seedRand = (num, range) => {
// Generate number multiplication
num = String(num).split('').reduce((c, n) => (n != 0) ? c * n : c * c);
// Transform to match range
let s = range[0],
e = range[1]
while(num < range[0] || num > range[1]) {
if(num > range[1]) num = Math.floor(num / e--);
if(num < range[0]) num = Math.floor(num * s++);
}
// Return value
return num;
}
// Test
console.log(seedRand(1220501, [1, 20]));
console.log(seedRand(1520502, [1, 20]));
console.log(seedRand(1520502, [1, 20])); // Same seed as previous one
console.log(seedRand(1370503, [1, 20]));
console.log(seedRand(1370503, [1, 21])); // Same seed as previous one, different range