生成基于可重复伪随机数的坐标
我需要根据一组坐标生成可重复的伪随机数,以便使用给定的种子,我将始终为特定坐标生成相同的值。
我想我应该使用类似这样的种子:
/* 64bit seed value*/
struct seed_cord {
uint16 seed;
uint16 coord_x_int;
uint16 coord_y_int;
uint8 coord_x_frac;
uint8 coord_y_frac;
}
其中 coord_x_int 是坐标的整数部分,小数部分由 coord_x_frac / 0xFF 给出。 seed
是一个随机的预先确定的值。
但我必须承认,试图理解 PRNG 的所有复杂性有点让人不知所措。对于我正在尝试的事情来说,什么是好的生成器?
我在快速 groovy 脚本中使用此方案测试了 Java 的 PRNG,结果如下:
显然,这很难说是体面的随机性。
我使用的脚本是:
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
short shortSeed = new Random().next(16) as short
def image = new BufferedImage(512, 512, BufferedImage.TYPE_BYTE_GRAY)
def raster = image.getRaster()
//x
(0..1).each{ x ->
(0..255).each{ xFrac ->
//y
(0..1).each{ y ->
(0..255).each{ yFrac ->
long seed = (shortSeed as long) << 48 |
(x as long) << 32 |
(y as long) << 16 |
(xFrac as long) << 8 |
(yFrac as long)
def value = new Random(seed).next(8)
raster.setSample( (x? xFrac+256 : xFrac), (y? yFrac+256 : yFrac), 0 , value)
}}}}
ImageIO.write(image, "PNG", new File("randomCoord.png"))
I need to generate repeatable pseudo random numbers based on a set of coordinates, so that with a given seed, I will always generate the same value for a specific coordinate.
I figured I'd use something like this for the seed:
/* 64bit seed value*/
struct seed_cord {
uint16 seed;
uint16 coord_x_int;
uint16 coord_y_int;
uint8 coord_x_frac;
uint8 coord_y_frac;
}
Where coord_x_int
is the integer part of the coordinate, and the fraction part is given by coord_x_frac / 0xFF
. seed
is a randomly pre-determined value.
But I must admit, trying to understand all the intricacies of PRNGs is a little overwhelming. What would be a good generator for what I'm attempting?
I tested out Java's PRNG using using this scheme in a quick groovy script, with the following result:
Obviously, this is hardly decent randomness.
The script I used was:
import java.awt.image.BufferedImage
import javax.imageio.ImageIO
short shortSeed = new Random().next(16) as short
def image = new BufferedImage(512, 512, BufferedImage.TYPE_BYTE_GRAY)
def raster = image.getRaster()
//x
(0..1).each{ x ->
(0..255).each{ xFrac ->
//y
(0..1).each{ y ->
(0..255).each{ yFrac ->
long seed = (shortSeed as long) << 48 |
(x as long) << 32 |
(y as long) << 16 |
(xFrac as long) << 8 |
(yFrac as long)
def value = new Random(seed).next(8)
raster.setSample( (x? xFrac+256 : xFrac), (y? yFrac+256 : yFrac), 0 , value)
}}}}
ImageIO.write(image, "PNG", new File("randomCoord.png"))
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
如果您确实只查看 512x512,那么呃...您感兴趣的 218 像素。
对于具有良好 ole MD5(128 位输出)的此类人群来说,有足够的空间。
如果您需要这种输出,您可以只采用整数的最低 32 位。实际上,任何输出空间至少与 int 一样大的哈希算法都可以。
现在,如果你偏执的话,你可以做各种有趣的事情。从坐标的哈希开始,然后将结果输入安全随机数生成器 (java.security.SecureRandom)。然后用盐将其散列 1000 次,盐是你的生日连接 (x+y) 次。
开个玩笑,随机数生成器并不一定会根据种子的微小变化而产生截然不同的结果。它们被设计为在开始重复之前有一个真正超级长的生成数字链,同时使这些链相当均匀地分布在数字空间中。
另一方面,SecureRandom 被设计为具有关于种子的混乱的附加特征。
If you're really only looking at 512x512, then that's uh... 218 pixels you're interested in.
There's plenty of space for that kind of population with good ole MD5 (128 bit output).
You can just take the lowest 32 bits for an integer if that's the kind of output you need. Really, any sort of hashing algorithm that has an output space at least as large as an int will do.
Now, you can do all sorts of fun stuff if you're paranoid. Start with a hash of your coordinates, then feed the result into a secure random number generator (java.security.SecureRandom). Then hash it 1000 times with a salt that's your birthday concatenated (x+y) times.
Joking aside, random number generators don't necessarily have wildly varying results based on small variations of the seed. They're designed to have a really, super duper long chain of generated numbers before they start repeating, while having those chains pretty evenly distributed among the number space.
On the other hand, the SecureRandom is designed to have the additional feature of being chaotic in regard to the seed.
大多数语言都有一个(或两个)PRNG 包,可让您使用特定种子初始化生成器。 PRNG 通常也可以作为更大的加密包的一部分出现;它们往往比通用库中的功能更强一些。
Most languages have a PRNG package (or two) that lets you initialize the generator with a specific seed. PRNGs can also often be found as part of a larger cryptographic package; they tend to be a bit stronger than those found in general-purpose libraries.
我会采用我创建的这样一个程序,然后修改它来选择坐标:
对 drand# 的调用为您提供从 0 到 1 的随机数,只需将其乘以每个所需向量所需的范围 p2$ 就是密码传递给密码处理程序,该处理程序将其与其他一些随机字符组合,然后将大小限制为一定限制 p1$ 是包含最终修改密码的位置
drand# 本身调用另一个 sub,它实际上是其自身的克隆,并进行了一些改组
排序可以确保生成的数字是真正随机的,还有一个值表被添加到要添加的值中,所有这些总共使 RNG 的随机性比没有时要多得多。
该 RNG 对初始设置的密码的细微差异具有非常高的敏感性,但是您必须进行初始调用以设置并初始化以“引导”随机数生成器该 RNG 将生成真正的随机数,将通过所有随机性测试
甚至比用手洗一副牌更随机,比掷骰子更随机。
希望这有助于使用相同的密码将导致相同的向量序列
该程序必须稍作修改以选择随机向量而不是
它目前用作安全加密随机数生成器......
I would take a program like this one I have created and then modify it to pick coordinates:
the call to drand# gives you random numbers from 0 to 1 simply multiply that by your needed range for each vector needed p2$ is the password that is passed to the password handler which combines it with some other random characters and then caps the size to a certain limit p1$ is where the final modified password is contained
drand# itself calls another sub which is actually a clone of itself with some shuffling of
sorts that works to ensure that the numbers being produced are truly random there is also a table of values that are added in to the values being added all this in total makes the RNG many many more times random with than without.
this RNG has a very high sensitivity to slight differences in password initially set you must however make an intial call to setup and initialize to "bootstrap" the random number generator this RNG will produce Truly random numbers that will pass all tests of randomness
more random even then shuffling a deck of cards by hand , more random than rolling a dice..
hope this helps using the same password will result in the same sequnece of vectors
This program would have to be modified a bit though to pick random vectors rather than
it's current use as a secure encryption random number generator...
您可以使用加密来执行此任务,例如 AES。使用您的种子作为密码,以坐标作为数据块进行结构并对其进行加密。加密的块将是您的随机数(您实际上可以使用它的任何部分)。此方法用于 Fortuna PRNG。相同的方法可用于需要随机访问数据的磁盘加密(请参阅使用 Fortuna PRNG 在计数器模式下使用 AES 进行随机访问加密:)
You can use encryption for this task, for example AES. Use your seed as the password, struct with coordinates as the data block and encrypt it. The encrypted block will be your random number (you can actually use any part of it). This approach is used in the Fortuna PRNG. The same approach can be used for disk encryption where random access of data is needed (see Random access encryption with AES In Counter mode using Fortuna PRNG:)