1

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

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

/* 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 / 0xFFseed是一个随机的预定值。

但我必须承认,试图理解 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"))
4

4 回答 4

1

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

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

如果这是您需要的输出类型,您可以只取整数的最低 32 位。实际上,任何具有至少与 int 一样大的输出空间的散列算法都可以。

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

开个玩笑,随机数生成器不一定会基于种子的微小变化而产生巨大变化的结果。它们的设计目的是在开始重复之前拥有一个非常、超级长的生成数字链,同时让这些链在数字空间中相当均匀地分布。

另一方面,SecureRandom 被设计为具有关于种子的混乱的附加特征。

于 2011-05-24T08:48:11.017 回答
0

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

于 2011-05-23T14:15:55.547 回答
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# 本身调用另一个子,它实际上是它自己的一个克隆,具有一些排序,可以确保生成的数字是真正随机的,还有一个值表添加到要添加的值中,所有这些总共使 RNG 随机的次数比没有随机的次数多得多。

此 RNG 对初始设置的密码的细微差异具有非常高的敏感性,但是您必须进行初始调用以设置和初始化以“引导”随机数生成器此 RNG 将产生真正的随机数,它将通过所有随机性测试甚至更随机然后用手洗一副牌,比掷骰子更随机..希望这有助于使用相同的密码将产生相同的向量序列

该程序必须进行一些修改以选择随机向量,而不是当前用作安全加密随机数生成器...

于 2012-01-27T15:19:31.157 回答
0

您可以为此任务使用加密,例如 AES。使用您的种子作为密码,使用坐标作为数据块的结构并对其进行加密。加密块将是您的随机数(您实际上可以使用它的任何部分)。Fortuna PRNG中使用了这种方法。相同的方法可用于需要随机访问数据的磁盘加密(请参阅使用 Fortuna PRNG 在计数器模式下使用 AES 进行随机访问加密:)

于 2012-05-14T08:50:19.897 回答