生成基于可重复伪随机数的坐标

时间:2011-05-23 14:10:10

标签: algorithm random prng

我需要根据一组坐标生成可重复的伪随机数,这样对于给定的种子,我将始终为特定坐标生成相同的值。

我想我会为种子使用这样的东西:

/* 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,结果如下:

Random Seeded image

显然,这不是很好的随机性。

我使用的脚本是:

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"))

4 个答案:

答案 0 :(得分:1)

如果你真的只看512x512,那就是你感兴趣的那个...... 18 像素。

对于那种具有良好的MD5(128位输出)的人群来说,有足够的空间。

如果这是您需要的输出类型,您可以将最低32位用于整数。实际上,任何类型的哈希算法的输出空间至少与int一样大。

现在,如果你是偏执狂,你可以做各种有趣的事情。从坐标的哈希开始,然后将结果提供给安全的随机数生成器(java.security.SecureRandom)。然后用你的生日连续(x + y)次的盐哈希1000次。

除了开玩笑,随机数生成器不一定会根据种子的微小变化而产生大不相同的结果。它们被设计成在它们开始重复之前具有真正的超级生成数字的长链,同时使这些链在数字空间中非常均匀地分布。

另一方面,SecureRandom的设计具有与种子相关的额外特征。

答案 1 :(得分:0)

大多数语言都有一个PRNG包(或两个),允许您使用特定种子初始化生成器。 PRNG通常也可以作为更大的加密包的一部分找到;它们往往比通用库中的那些更强大。

答案 2 :(得分:0)

我会选择一个我创建的程序,然后修改它以选择坐标:

REM $DYNAMIC
COMMON SHARED n%, rbuf%, sz%, sw%, p1$
DECLARE SUB initialize ()
DECLARE SUB filbuf ()
DECLARE SUB setup ()
DECLARE FUNCTION Drnd# ()
DECLARE SUB core ()
DECLARE SUB modify ()
DIM SHARED pad1(340) AS STRING * 1
DIM SHARED trnsltr(66) AS STRING * 1 ' translates a 0-67 value into a pad character
DIM SHARED trnslt(255) AS INTEGER  'translates a pad value to 0-67 value -1 if error
DIM SHARED moders(26) AS INTEGER 'modding function prim number array
DIM SHARED moders2(26) AS INTEGER 'modding function prim number array
DIM SHARED ranbuf(1 TO 42) AS DOUBLE 'random number buffer if this is full and rbuf %>0
REM then this buffer is used to get new random values
REM rbuf% holds the index of the next random number to be used
REM subroutine setup loads the prime number table
REM from the data statements to be used
REM as modifiers in two different ways (or more)
REM subroutine initialize primes the pad array with initial values
REM transfering the values from a string into an array then
REM makes the first initial scrambling of this array
REM initializing pad user input phase:
CLS
INPUT "full name of file to be encrypted"; nam1$
INPUT "full name of output file"; nam2$
INPUT "enter password"; p2$
rbuf% = 0
n% = 0: sw% = 0
p3$ = STRING$(341, "Y")
p1$ = "Tfwd+-$wiHEbeMN<wjUHEgwBEGwyIEGWYrg3uehrnnqbwurt+>Hdgefrywre"
p1$ = p2$ + p1$ + p3$
PRINT "hit any key to continue any time after a display and after the graphic display"
p1$ = LEFT$(p1$, 341)
sz% = LEN(p1$)
CALL setup
CALL initialize
CLS
ibfr$ = STRING$(512, 32)
postn& = 1
OPEN nam1$ FOR BINARY AS #1
OPEN nam2$ FOR BINARY AS #2
g& = LOF(1)
max& = g&
sbtrct% = 512
WHILE g& > 0
LOCATE 1, 1
PRINT INT(1000 * ((max& - g&) / max&)) / 10; "% done";
IF g& < 512 THEN
ibfr$ = STRING$(g&, 32)
sbtrct% = g&
END IF
GET #1, postn&, ibfr$
FOR ste% = 1 TO LEN(ibfr$)
geh% = INT(Drnd# * 256)
MID$(ibfr$, ste%, 1) = CHR$(geh% XOR ASC(MID$(ibfr$, ste%, 1)))
NEXT ste%
PUT #2, postn&, ibfr$
postn& = postn& + sbtrct%
g& = g& - sbtrct%
WEND
CLOSE #2
CLOSE #1
PRINT "hit any key to exit"
i$ = ""
WHILE i$ = "": i$ = INKEY$: WEND
SYSTEM
END
DATA 3,5,7,9,11,13,17,19
DATA 23,29,33,37,43,47
DATA 53,59,67,71,73,79,83
DATA 89,91,97,101,107,109
DATA 43,45,60,62,36

REM $STATIC
SUB core
REM shuffling algorythinm
FOR a% = 0 TO 339
m% = (a% + 340) MOD 341: bez% = trnslt(ASC(pad1(340)))
IF n% MOD 3 = 0 THEN pad1(340) = trnsltr((2 * trnslt(ASC(pad1(a%))) + 67 -   trnslt(ASC(pad1(m%)))) MOD 67)
IF n% MOD 3 = 1 THEN pad1(340) = trnsltr((2 * (67 - trnslt(ASC(pad1(a%)))) + 67 - trnslt(ASC(pad1(m%)))) MOD 67)
IF n% MOD 3 = 2 THEN pad1(340) = trnsltr(((2 * trnslt(ASC(pad1(a%))) + 67 - trnslt(ASC(pad1(m%)))) + moders(n% MOD 27)) MOD 67)
pad1(a% + 1) = pad1(m%): n% = (n% + 1) MOD 32767
pad1(a%) = trnsltr((bez% + trnslt(ASC(pad1(m%)))) MOD 67)
NEXT a%
sw% = (sw% + 1) MOD 32767
END SUB

FUNCTION Drnd#
IF rbuf% = 0 THEN
CALL core
CALL filbuf
IF sw% = 32767 THEN CALL modify
END IF
IF rbuf% > 0 THEN yut# = ranbuf(rbuf%)
rbuf% = rbuf% - 1
Drnd# = yut#
END FUNCTION

SUB filbuf
q% = 42: temp# = 0
WHILE q% > 0
FOR p% = 1 TO 42
k% = (p% - 1) * 8
FOR e% = k% TO k% + 7
temp# = temp# * 67: hug# = ABS(trnslt(ASC(pad1(e%)))): temp# = temp# + hug#
NEXT e%
IF temp# / (67 ^ 8) >= 0 AND q% < 43 THEN
ranbuf(q%) = temp# / (67 ^ 8): q% = q% - 1
END IF
temp# = 0
NEXT p%
WEND
rbuf% = 42
END SUB

SUB initialize
FOR a% = 0 TO 340
pad1(a%) = MID$(p1$, a% + 1, 1)
NEXT a%
FOR a% = 0 TO 340
LOCATE 1, 1
IF a% MOD 26 = 0 THEN PRINT INT((340 - a%) / 26)
sum% = 0
FOR b% = 0 TO 340
qn% = INT(Drnd# * 81)
op% = INT(qn% / 3)
qn% = qn% MOD 3
IF qn% = 0 THEN sum% = sum% + trnslt(ASC(pad1(b%)))
IF qn% = 1 THEN sum% = sum% + (67 + 66 - trnslt(ASC(pad1(b%)))) MOD 67
IF qn% = 2 THEN sum% = sum% + trnslt(ASC(pad1(b%))) + moders(op%)
NEXT b%
pad1(a%) = trnsltr(sum% MOD 67)
NEXT a%
n% = n% + 1
END SUB

SUB modify
REM modifier shuffling routine
q% = 26
temp# = 0
WHILE q% > -1
FOR p% = 1 TO 27
k% = (p% - 1) * 4 + 3
FOR e% = k% TO k% + 3
temp# = temp# * 67
hug# = ABS(trnslt(ASC(pad1(e%))))
temp# = temp# + hug#
NEXT e%
IF (temp# / (67 ^ 4)) >= 0 AND q% > -1 THEN
SWAP moders(q%), moders(INT(27 * (temp# / (67 ^ 4))))
q% = q% - 1
END IF
temp# = 0
NEXT p%
WEND
END SUB

SUB setup
FOR a% = 0 TO 26
READ moders(a%)
moders2(a%) = moders(a%)
NEXT a%
REM setting up tables and modder functions
FOR a% = 0 TO 25
trnsltr(a%) = CHR$(a% + 97)
trnsltr(a% + 26) = CHR$(a% + 65)
NEXT a%
FOR a% = 52 TO 61
trnsltr(a%) = CHR$(a% - 4)
NEXT a%
FOR a% = 62 TO 66
READ b%
trnsltr(a%) = CHR$(b%)
NEXT a%
FOR a% = 0 TO 255
trnslt(a%) = -1
NEXT a%
FOR a% = 0 TO 66
trnslt(ASC(trnsltr(a%))) = a%
NEXT a%
RESTORE
END SUB

对drand#的调用给出了0到1之间的随机数,只需乘以你需要的每个向量所需的范围p2 $是传递给密码处理程序的密码,它将它与其他一些随机字符组合,然后再加上大写大小到某个限制p1 $是包含最终修改密码的位置 drand#本身调用另一个sub,它实际上是一个自己的克隆,有一些改组 为了确保正在生成的数字是真正随机的,还有一个值列表,这些值被添加到要添加的值中,所有这些使得RNG随机而不是没有多次。

这个RNG对初始设置的密码的微小差异具有非常高的敏感性你必须初步调用设置并初始化为“自举”随机数发生器这个RNG将产生真正的随机数,将通过所有随机性测试 更随机的,即使用手拖动一副纸牌,比滚动骰子更随机.. 希望这有助于使用相同的密码将导致相同的矢量序列

这个程序必须稍微修改一下才能选择随机向量而不是 它目前用作安全加密随机数生成器......

答案 3 :(得分:0)

您可以对此任务使用加密,例如AES。使用种子作为密码,使用坐标作为数据块并加密它。加密块将是您的随机数(您实际上可以使用它的任何部分)。这种方法用于Fortuna PRNG。相同的方法可用于需要随机访问数据的磁盘加密(参见Random access encryption with AES In Counter mode using Fortuna PRNG: