可植入 JavaScript 随机数生成器
JavaScript Math.random()< /code>
函数返回 0 到 1 之间的随机值,根据当前时间自动播种(我相信类似于 Java)。 但是,我认为没有任何方法可以为其设置自己的种子。
如何制作一个随机数生成器,我可以为其提供自己的种子值,以便我可以让它生成可重复的(伪)随机数序列?
The JavaScript Math.random()
function returns a random value between 0 and 1, automatically seeded based on the current time (similar to Java I believe). However, I don't think there's any way to set you own seed for it.
How can I make a random number generator that I can provide my own seed value for, so that I can have it produce a repeatable sequence of (pseudo)random numbers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
如果您不需要播种功能,只需使用 Math.random() 并围绕它构建辅助函数(例如,randRange(start, end))。
我不确定您使用的是什么 RNG,但最好了解并记录它,以便您了解其特征和局限性。
正如 Starkii 所说,Mersenne Twister 是一个很好的 PRNG,但实现起来并不容易。 如果您想自己尝试实现 LCG - 它非常简单,具有良好的随机性质量(不如 Mersenne Twister),并且您可以使用一些流行的常量。
编辑:考虑这个答案中用于短可种子RNG实现的绝佳选项,包括LCG选项。
If you don't need the seeding capability just use
Math.random()
and build helper functions around it (eg.randRange(start, end)
).I'm not sure what RNG you're using, but it's best to know and document it so you're aware of its characteristics and limitations.
Like Starkii said, Mersenne Twister is a good PRNG, but it isn't easy to implement. If you want to do it yourself try implementing a LCG - it's very easy, has decent randomness qualities (not as good as Mersenne Twister), and you can use some of the popular constants.
EDIT: consider the great options at this answer for short seedable RNG implementations, including an LCG option.
如果您希望能够指定种子,只需替换对
getSeconds()
和getMinutes()
的调用即可。 您可以传入一个 int 并使用它的一半 mod 60 作为秒值,另一半 modulo 60 给出另一部分。话虽这么说,这个方法看起来很垃圾。 生成正确的随机数非常困难。 这样做的明显问题是随机数种子是基于秒和分钟的。 要猜测种子并重新创建随机数流,只需尝试 3600 种不同的秒和分钟组合。 这也意味着只有 3600 种不同的可能种子。 这是可以纠正的,但我从一开始就对这个 RNG 表示怀疑。
如果您想使用更好的 RNG,请尝试 Mersenne Twister。 它是一款经过充分测试且相当稳健的 RNG,具有巨大的轨道和出色的性能。
编辑:我真的应该是正确的,并将其称为伪随机数生成器或 PRNG。
If you want to be able to specify the seed, you just need to replace the calls to
getSeconds()
andgetMinutes()
. You could pass in an int and use half of it mod 60 for the seconds value and the other half modulo 60 to give you the other part.That being said, this method looks like garbage. Doing proper random number generation is very hard. The obvious problem with this is that the random number seed is based on seconds and minutes. To guess the seed and recreate your stream of random numbers only requires trying 3600 different second and minute combinations. It also means that there are only 3600 different possible seeds. This is correctable, but I'd be suspicious of this RNG from the start.
If you want to use a better RNG, try the Mersenne Twister. It is a well tested and fairly robust RNG with a huge orbit and excellent performance.
EDIT: I really should be correct and refer to this as a Pseudo Random Number Generator or PRNG.
我使用 Mersenne Twister 的 JavaScript 端口:
https://gist.github.com/300494
它允许您手动设置种子。 另外,正如其他答案中提到的,Mersenne Twister 是一个非常好的 PRNG。
I use a JavaScript port of the Mersenne Twister:
https://gist.github.com/300494
It allows you to set the seed manually. Also, as mentioned in other answers, the Mersenne Twister is a really good PRNG.
您列出的代码看起来像 Lehmer RNG< /a>. 如果是这种情况,则
2147483647
是最大的 32 位有符号整数,2147483647
是最大的 32 位素数,48271
是用于生成数字的全周期乘数。如果这是真的,您可以修改
RandomNumberGenerator
以接受额外参数seed
,然后将this.seed
设置为seed< /代码>; 但你必须小心确保种子会产生良好的随机数分布(莱默可能会很奇怪)——但大多数种子都会很好。
The code you listed kind of looks like a Lehmer RNG. If this is the case, then
2147483647
is the largest 32-bit signed integer,2147483647
is the largest 32-bit prime, and48271
is a full-period multiplier that is used to generate the numbers.If this is true, you could modify
RandomNumberGenerator
to take in an extra parameterseed
, and then setthis.seed
toseed
; but you'd have to be careful to make sure the seed would result in a good distribution of random numbers (Lehmer can be weird like that) -- but most seeds will be fine.以下是可以提供自定义种子的 PRNG。 调用
SeedRandom
将返回一个随机生成器函数。 可以不带参数调用SeedRandom
,以便使用当前时间为返回的随机函数提供种子,也可以使用 1 或 2 个非负整数作为参数来调用它,以便使用这些值作为种子整数。 由于浮点精度,只有 1 个值的播种将只允许生成器启动到 2^53 种不同状态之一。返回的随机生成器函数接受 1 个名为
limit
的整数参数,limit 必须在 1 到 4294965886 范围内,函数将返回 0 到 limit-1 范围内的数字。使用示例:
该生成器具有以下属性:
mod
值为素数,因此无论选择的限制如何,输出中都没有简单的模式。 这与一些更简单的 PRNG 不同,它们表现出一些相当系统的模式。奖金:打字版本< /a>
The following is a PRNG that may be fed a custom seed. Calling
SeedRandom
will return a random generator function.SeedRandom
can be called with no arguments in order to seed the returned random function with the current time, or it can be called with either 1 or 2 non-negative inters as arguments in order to seed it with those integers. Due to float point accuracy seeding with only 1 value will only allow the generator to be initiated to one of 2^53 different states.The returned random generator function takes 1 integer argument named
limit
, the limit must be in the range 1 to 4294965886, the function will return a number in the range 0 to limit-1.Example use:
This generator exhibit the following properties:
mod
values being primes there is no simple pattern in the output, no matter the chosen limit. This is unlike some simpler PRNGs that exhibit some quite systematic patterns.Bonus: typescript version
如果您使用 Typescript 进行编程,我会采用 Christoph Henkelmann 对此线程的回答中引入的 Mersenne Twister 实现作为 Typescript 类:
您可以按如下方式使用它:
检查源代码以获取更多方法。
If you program in Typescript, I adapted the Mersenne Twister implementation that was brought in Christoph Henkelmann's answer to this thread as a typescript class:
you can than use it as follows:
check the source for more methods.
这是一个我喜欢使用的非常有效但简单的 javascript PRNG 函数:
我希望这就是您正在寻找的。
Here is quite an effective but simple javascript PRNG function that I like to use:
I hope this is what you're looking for.
谢谢你,@aaaaaaaaaaaa(接受的答案)
我真的需要一个好的非库解决方案(更容易嵌入)
所以......我创建了这个类来存储种子并允许Unity式的“下一步”......但保留了基于初始整数的结果
然后用这些检查它...似乎与随机(但可查询)种子值(a la Minecraft)配合得很好,甚至存储了返回的最后一个值(如果需要),
该值应该输出(对于每个人)
编辑:如果您需要重新播种或测试值,我使 init() 起作用(这在我的上下文中也是必要的)
Thank you, @aaaaaaaaaaaa (Accepted Answer)
I really needed a good non-library solution (easier to embed)
so... i made this class to store the seed and allow a Unity-esque "Next" ... but kept the initial Integer based results
And then checked it with these... seems to work well with random (but queryable) seed value (a la Minecraft) and even stored the last value returned (if needed)
which should output (for everybody)
EDIT: I made the init() work if you ever needed to reseed, or were testing values (this was necessary in my context as well)
我发现这段代码很有效,它似乎可以很好地获取随机数,然后使用种子,但是我不太确定逻辑是如何工作的(例如 2345678901、48271 和 2147483647 数字来自哪里)。
I found this code kicking around and it appears to work fine for getting a random number and then using the seed afterward but I'm not quite sure how the logic works (e.g. where the 2345678901, 48271 & 2147483647 numbers came from).
以下 IIFE 生成一长串可重复的随机 31 位整数。 它使用两个 15 位素数来避免 JS 整数溢出。
下面的代码展示了如何使用它......
The following IIFE generates a long sequence of reproducible random 31-bit integers. It uses two 15-bit primes to avoid overflowing JS integers.
The following code shows how to use it...
好的,这是我确定的解决方案。
首先,使用“newseed()”函数创建一个种子值。 然后将种子值传递给“srandom()”函数。 最后,“srandom()”函数返回 0 到 1 之间的伪随机值。
关键点是种子值存储在数组内。 如果它只是一个整数或浮点数,则每次调用函数时该值都会被覆盖,因为整数、浮点数、字符串等的值直接存储在堆栈中,而不是像数组和指针那样存储在堆栈中其他物体。 因此,种子的价值有可能保持持久。
最后,可以定义“srandom()”函数,使其成为“Math”对象的方法,但我将把它留给您来解决。 ;)
祝你好运!
JavaScript:
Lua 4(我个人的目标环境):
OK, here's the solution I settled on.
First you create a seed value using the "newseed()" function. Then you pass the seed value to the "srandom()" function. Lastly, the "srandom()" function returns a pseudo random value between 0 and 1.
The crucial bit is that the seed value is stored inside an array. If it were simply an integer or float, the value would get overwritten each time the function were called, since the values of integers, floats, strings and so forth are stored directly in the stack versus just the pointers as in the case of arrays and other objects. Thus, it's possible for the value of the seed to remain persistent.
Finally, it is possible to define the "srandom()" function such that it is a method of the "Math" object, but I'll leave that up to you to figure out. ;)
Good luck!
JavaScript:
Lua 4 (my personal target environment):