可种子JavaScript随机数生成器
JavaScript函数返回一个介于0和1之间的随机值,根据当前时间自动设定种子(我相信与Java类似)。然而,我不认为有任何方法可以让你为它播下自己的种子可种子JavaScript随机数生成器,javascript,random,seed,Javascript,Random,Seed,JavaScript函数返回一个介于0和1之间的随机值,根据当前时间自动设定种子(我相信与Java类似)。然而,我不认为有任何方法可以让你为它播下自己的种子 如何制作一个随机数生成器,为其提供自己的种子值,以便生成可重复的(伪)随机数序列?如果希望能够指定种子,只需替换对getSeconds()和getMinutes()的调用即可。你可以传入一个整数,用它的一半mod 60表示秒值,另一半mod 60表示另一部分 也就是说,这个方法看起来像垃圾。正确地生成随机数是非常困难的。这样做的明显问题是,
如何制作一个随机数生成器,为其提供自己的种子值,以便生成可重复的(伪)随机数序列?如果希望能够指定种子,只需替换对
getSeconds()
和getMinutes()
的调用即可。你可以传入一个整数,用它的一半mod 60表示秒值,另一半mod 60表示另一部分
也就是说,这个方法看起来像垃圾。正确地生成随机数是非常困难的。这样做的明显问题是,随机数种子基于秒和分钟。猜测种子并重新创建随机数流只需要尝试3600种不同的秒和分钟组合。这也意味着只有3600种不同的种子。这是可以纠正的,但我从一开始就怀疑这个RNG
如果您想使用更好的RNG,请尝试。这是一个经过良好测试且相当坚固的RNG,具有巨大的轨道和优异的性能
编辑:我真的应该是正确的,并将其称为伪随机数生成器或PRNG
“任何使用算术方法产生随机数的人都处于罪恶状态。”---约翰·冯·诺依曼
如果不需要种子设定功能,只需使用
Math.random()
并围绕它构建辅助函数(例如randRange(start,end)
)
我不确定您使用的是什么RNG,但最好了解并记录它,以便了解其特点和局限性
正如Starkii所说,Mersenne Twister是一个很好的PRNG,但它不容易实现。如果你想自己做的话,试着实现一个-它非常简单,有相当好的随机性(没有Mersenne Twister好),你可以使用一些流行的常量
<>编辑:考虑短期可移植RNG实现的大选项,包括LCG选项。
函数RNG(种子){
//使用GCC常数的LCG
this.m=0x8000000;//2**31;
此参数a=1103515245;
这个c=12345;
this.state=seed?seed:Math.floor(Math.random()*(this.m-1));
}
RNG.prototype.nextInt=函数(){
this.state=(this.a*this.state+this.c)%this.m;
返回此.state;
}
RNG.prototype.nextFloat=函数(){
//返回范围为[0,1]
返回此.nextInt()/(this.m-1);
}
RNG.prototype.nextRange=函数(开始、结束){
//返回范围[开始,结束]:包括开始,不包括结束
//由于低位的弱随机性,无法对nextInt进行模化
var rangeSize=结束-开始;
var randomUnder1=this.nextInt()/this.m;
返回开始+数学楼层(随机小于1*rangeSize);
}
RNG.prototype.choice=函数(数组){
返回数组[this.nextRange(0,array.length)];
}
var rng=新rng(20);
对于(变量i=0;i<10;i++)
console.log(rng.nextRange(10,50));
变量数字=['0','1','2','3','4','5','6','7','8','9'];
对于(变量i=0;i<10;i++)
console.log(rng.choice(digits));
您列出的代码看起来有点像。如果是这种情况,那么2147483647
是最大的32位有符号整数,2147483647
是最大的32位素数,48271
是用于生成数字的全周期乘法器
如果这是真的,您可以修改
RandomNumberGenerator
以获取一个额外的参数seed
,然后将this.seed
设置为seed
;但是您必须小心确保seed将导致随机数的良好分布(莱默可能会很奇怪)--但大多数种子都会很好。其中一个选项是基于可种子RC4的Math.random()替换为具有良好属性的drop-in。好的,这是我确定的解决方案
首先使用“newseed()”函数创建种子值。然后将种子值传递给“srandom()”函数。最后,“srandom()”函数返回一个介于0和1之间的伪随机值
关键是种子值存储在数组中。如果它只是一个整数或浮点数,那么每次调用函数时,该值都会被覆盖,因为整数、浮点数、字符串等的值直接存储在堆栈中,而不像数组和其他对象那样仅存储在指针中。因此,它是p种子的价值很可能保持不变
最后,可以定义“srandom()”函数,使其成为“Math”对象的一种方法,但这要由您自己来决定
祝你好运
JavaScript:
// Global variables used for the seeded random functions, below.
var seedobja = 1103515245
var seedobjc = 12345
var seedobjm = 4294967295 //0x100000000
// Creates a new seed for seeded functions such as srandom().
function newseed(seednum)
{
return [seednum]
}
// Works like Math.random(), except you provide your own seed as the first argument.
function srandom(seedobj)
{
seedobj[0] = (seedobj[0] * seedobja + seedobjc) % seedobjm
return seedobj[0] / (seedobjm - 1)
}
// Store some test values in variables.
var my_seed_value = newseed(230951)
var my_random_value_1 = srandom(my_seed_value)
var my_random_value_2 = srandom(my_seed_value)
var my_random_value_3 = srandom(my_seed_value)
// Print the values to console. Replace "WScript.Echo()" with "alert()" if inside a Web browser.
WScript.Echo(my_random_value_1)
WScript.Echo(my_random_value_2)
WScript.Echo(my_random_value_3)
Lua 4(我的个人目标环境):
我使用Mersenne Twister的JavaScript端口: 它允许您手动设置种子。此外,正如其他答案中提到的,Mersenne捻线机是一种非常好的PRNG 注意:此代码最初包含在上面的问题中。为了保持问题的简短和重点,我将其移至此社区Wiki答案中 我发现这段代码很活跃,它似乎可以很好地获得一个随机数,然后再使用seed,但我不太确定逻辑是如何工作的(例如2345678901、48271和2147483647数字来自哪里)
以下是一个可以提供自定义种子的PRNG。调用
SeedRandom
将返回一个随机生成器函数。SeedRandom
可以在没有参数的情况下调用,以便在当前时间为返回的随机函数进行种子设定,也可以使用1或2个非负inters作为参数进行调用,以便为其进行种子设定由于浮点精度,只有1个值的播种将只允许生成器t
-- Global variables used for the seeded random functions, below.
seedobja = 1103515.245
seedobjc = 12345
seedobjm = 4294967.295 --0x100000000
-- Creates a new seed for seeded functions such as srandom().
function newseed(seednum)
return {seednum}
end
-- Works like random(), except you provide your own seed as the first argument.
function srandom(seedobj)
seedobj[1] = mod(seedobj[1] * seedobja + seedobjc, seedobjm)
return seedobj[1] / (seedobjm - 1)
end
-- Store some test values in variables.
my_seed_value = newseed(230951)
my_random_value_1 = srandom(my_seed_value)
my_random_value_2 = srandom(my_seed_value)
my_random_value_3 = srandom(my_seed_value)
-- Print the values to console.
print(my_random_value_1)
print(my_random_value_2)
print(my_random_value_3)
function nextRandomNumber(){
var hi = this.seed / this.Q;
var lo = this.seed % this.Q;
var test = this.A * lo - this.R * hi;
if(test > 0){
this.seed = test;
} else {
this.seed = test + this.M;
}
return (this.seed * this.oneOverM);
}
function RandomNumberGenerator(){
var d = new Date();
this.seed = 2345678901 + (d.getSeconds() * 0xFFFFFF) + (d.getMinutes() * 0xFFFF);
this.A = 48271;
this.M = 2147483647;
this.Q = this.M / this.A;
this.R = this.M % this.A;
this.oneOverM = 1.0 / this.M;
this.next = nextRandomNumber;
return this;
}
function createRandomNumber(Min, Max){
var rand = new RandomNumberGenerator();
return Math.round((Max-Min) * rand.next() + Min);
}
//Thus I can now do:
var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var numbers = ['1','2','3','4','5','6','7','8','9','10'];
var colors = ['red','orange','yellow','green','blue','indigo','violet'];
var first = letters[createRandomNumber(0, letters.length)];
var second = numbers[createRandomNumber(0, numbers.length)];
var third = colors[createRandomNumber(0, colors.length)];
alert("Today's show was brought to you by the letter: " + first + ", the number " + second + ", and the color " + third + "!");
/*
If I could pass my own seed into the createRandomNumber(min, max, seed);
function then I could reproduce a random output later if desired.
*/
function SeedRandom(state1,state2){
var mod1=4294967087
var mul1=65539
var mod2=4294965887
var mul2=65537
if(typeof state1!="number"){
state1=+new Date()
}
if(typeof state2!="number"){
state2=state1
}
state1=state1%(mod1-1)+1
state2=state2%(mod2-1)+1
function random(limit){
state1=(state1*mul1)%mod1
state2=(state2*mul2)%mod2
if(state1<limit && state2<limit && state1<mod1%limit && state2<mod2%limit){
return random(limit)
}
return (state1+state2)%limit
}
return random
}
var generator1=SeedRandom() //Seed with current time
var randomVariable=generator1(7) //Generate one of the numbers [0,1,2,3,4,5,6]
var generator2=SeedRandom(42) //Seed with a specific seed
var fixedVariable=generator2(7) //First value of this generator will always be
//1 because of the specific seed.
/**
* copied almost directly from Mersenne Twister implementation found in https://gist.github.com/banksean/300494
* all rights reserved to him.
*/
export class Random {
static N = 624;
static M = 397;
static MATRIX_A = 0x9908b0df;
/* constant vector a */
static UPPER_MASK = 0x80000000;
/* most significant w-r bits */
static LOWER_MASK = 0x7fffffff;
/* least significant r bits */
mt = new Array(Random.N);
/* the array for the state vector */
mti = Random.N + 1;
/* mti==N+1 means mt[N] is not initialized */
constructor(seed:number = null) {
if (seed == null) {
seed = new Date().getTime();
}
this.init_genrand(seed);
}
private init_genrand(s:number) {
this.mt[0] = s >>> 0;
for (this.mti = 1; this.mti < Random.N; this.mti++) {
var s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30);
this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253)
+ this.mti;
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
/* In the previous versions, MSBs of the seed affect */
/* only MSBs of the array mt[]. */
/* 2002/01/09 modified by Makoto Matsumoto */
this.mt[this.mti] >>>= 0;
/* for >32 bit machines */
}
}
/**
* generates a random number on [0,0xffffffff]-interval
* @private
*/
private _nextInt32():number {
var y:number;
var mag01 = new Array(0x0, Random.MATRIX_A);
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (this.mti >= Random.N) { /* generate N words at one time */
var kk:number;
if (this.mti == Random.N + 1) /* if init_genrand() has not been called, */
this.init_genrand(5489);
/* a default initial seed is used */
for (kk = 0; kk < Random.N - Random.M; kk++) {
y = (this.mt[kk] & Random.UPPER_MASK) | (this.mt[kk + 1] & Random.LOWER_MASK);
this.mt[kk] = this.mt[kk + Random.M] ^ (y >>> 1) ^ mag01[y & 0x1];
}
for (; kk < Random.N - 1; kk++) {
y = (this.mt[kk] & Random.UPPER_MASK) | (this.mt[kk + 1] & Random.LOWER_MASK);
this.mt[kk] = this.mt[kk + (Random.M - Random.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
}
y = (this.mt[Random.N - 1] & Random.UPPER_MASK) | (this.mt[0] & Random.LOWER_MASK);
this.mt[Random.N - 1] = this.mt[Random.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
this.mti = 0;
}
y = this.mt[this.mti++];
/* Tempering */
y ^= (y >>> 11);
y ^= (y << 7) & 0x9d2c5680;
y ^= (y << 15) & 0xefc60000;
y ^= (y >>> 18);
return y >>> 0;
}
/**
* generates an int32 pseudo random number
* @param range: an optional [from, to] range, if not specified the result will be in range [0,0xffffffff]
* @return {number}
*/
nextInt32(range:[number, number] = null):number {
var result = this._nextInt32();
if (range == null) {
return result;
}
return (result % (range[1] - range[0])) + range[0];
}
/**
* generates a random number on [0,0x7fffffff]-interval
*/
nextInt31():number {
return (this._nextInt32() >>> 1);
}
/**
* generates a random number on [0,1]-real-interval
*/
nextNumber():number {
return this._nextInt32() * (1.0 / 4294967295.0);
}
/**
* generates a random number on [0,1) with 53-bit resolution
*/
nextNumber53():number {
var a = this._nextInt32() >>> 5, b = this._nextInt32() >>> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}
}
var random = new Random(132);
random.nextInt32(); //return a pseudo random int32 number
random.nextInt32([10,20]); //return a pseudo random int in range [10,20]
random.nextNumber(); //return a a pseudo random number in range [0,1]