如何种子生成随机数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何种子生成随机数?相关的知识,希望对你有一定的参考价值。

它不会产生预期的随机性。

我想从一个像66美元这样的种子开始,然后测量最后两个位,ror会给我下一个随机数,依此类推,但它只显示$ B3并且根本没有变化。

我打算怎么喂?随机上面的行显示了portc上的数字,因为我希望两个数字相继显示。

我只使用avr studio 4 for atmega 8535 at 1Mhz。

> ;Program to random numbers  on port C
> 
> ;Stack and Stack Pointer Addresses  .equ     SPH    =$3E             
> ;High Byte Stack Pointer Address   .equ     SPL    =$3D             
> ;Low Byte Stack Pointer Address 
> 
> .equ     RAMEND =$25F             ;Stack Address 
> 
> ;Port Addresses 
> 
> .equ     PORTC  =$15              ;Port C Output Address 
> 
> .equ     DDRC   =$14              ;Port C Data Direction Register
> Address 
> 
> .equ     numberoneddr=DDRC
> 
> .equ     numberoneport=portc
> 
> .equ     numbertwoddr=DDRC
> 
> .equ     numbertwoport=portc
> 
> .equ     delayCount=21
> 
> .equ    random1 =$66
> 
> ;Register Definitions 
> 
> .def    numberone   =r1               ;Register to store data pointed
> to by Z 
> 
> .def    numbertwo   =r2
> 
> .def     temp   =r16              ;Temporary storage register 
> 
> 
> 
> reset:
> 
> ; initialize stack pointer. Done automatically at reset on many AVRs
> 
>   ldi temp, low  (RAMEND)
> 
>   out spl, temp
> 
>   ldi temp, high (RAMEND)
> 
>   out sph, temp
> 
> 
> 
> 
> ;port initialisation
> 
> ldi temp,$FF
> 
> out numberoneddr,temp
> 
> out numberoneport,temp
> 
> out numbertwoddr,temp
> 
> out numbertwoport,temp
> 
> 
> 
> ;Program Initialisation 
> 
> ldi temp,$66
> 
> rcall random
> 
> mov   numberone, temp
> 
> out numberoneport,numberone
> 
> rcall random
> 
> mov   numbertwo, temp
> 
> out numberoneport,numbertwo
> 
> 
> 
> 
> random: mov r19,temp
> 
> ldi r17, 0x01
> 
> eor r19,r17
> 
> ror r19
> 
> mov temp,r19
> 
> ret
> 
> 
> 
> delay:
>         clr r20
> 
>       clr r21
> 
>       ldi r22, delayCount
> 
> loopDelay:
> 
>       dec r20
> 
>       brne loopDelay
> 
>       dec r21
> 
>       brne loopDelay
> 
>       dec r22
> 
>       brne loopDelay
> 
>         ret
答案

经过一些搜索我的古代asm源代码档案后,我发现这是我在以后使用的x86 MSDOS NASM平台:

;.rnd       ;al=rnd num <0,ah>;

.rnd:   pusha
    mov cx,ax

.rnd0:  mov bx,[cs:.rnddat]

    mov ax,[cs:.rndtim]
    xor al,bh
    add ah,bh
    rcr ax,3
    xor al,bl
    rcl ax,2

.rnd2:  cmp al,ch
    jbe .rnde
    sub al,ch
    or  ch,ch
    jnz .rnd2
    sub al,al

.rnde:  mov ah,bl
    mov [cs:.rnddat],ax
    or  al,1

    xor ax,[fs:046Ch]
    add [cs:.rndtim],ax
    popa
    mov al,[cs:.rnddat]
    ret
.rnddat:db  0,0
.rndtim:dw  0

想法是让一些存储的数字执行一些基本的ALU操作,如+,*,/,<<,>>,&,^但确保不发生饱和,并且通常交换一些值的H,L以保持随机性。所以把它移植到你的asm但我强烈建议你编写它并首先尝试在PC上查看随机性是否适合你的任务。

顺便说一下,你也可以使用程序存储器或任何ROM内容作为随机基础...这也是利用内部RTC块,所以你必须省略该部分或添加一个定时器或只是循环通过一堆非空数据。

[0000:046C] are 4 Bytes master clock count (long integer) 0 = midnight and increments until a 24 hour equiv.

我发现了我的老版本,名为NoSignal(1997年来自TASM),内部有rnd:

    .386P
    IDEAL
    MODEL TINY

    CODESEG
    STARTUPCODE
main:   mov ax,19   ;320*200*256
    int 16
    push 0A000h ;Video segment
    pop es      ;keyboard test,speaker delay v si=256

l0: ror ax,cl       ;rnd...ax
    add ax,di
    stosw       ;plot...
    loop r1     ;speaker delay...
    mov cx,si
    out 61h,al
r1: or di,di
    jnz l0
    push ax
    mov ah,1    ;test keyboard
    int 16h
    pop ax
    jz l0

ende:   sub ax,ax   ;turn off speaker and exit
    out 61h,al
    int 16h
    mov ax,3
    int 16
    ret
    END

它为屏幕和扬声器填充白噪声,就好像模拟电视中没有天线电缆一样。这个版本长44个字节,伪随机生成器从标签l0:开始

  • qazxsw poi是生成的数字(以及之前生成的数字,就像你的temp)
  • ax正在递增(类似于实际时间)......
  • di正在减少

所以如果我看对了它应该就够了:

cl

并根据需要添加 rnd:ror ax,cl ;rnd...ax add ax,di inc di dec cl ret 存储寄存器/值。如果你需要更复杂的东西,那就使用modulo prime算术。

[edit1]简单的C ++伪随机生成器

push/pop

上述随机生成器被加重到DOS环境时间或特殊用途。这个不是......随机性是这样的:

当我用它来填充NoSignal图像窗口时,结果如下:

这里是Gif动画:

NoSignal填充代码如下:

WORD rnd_d0=0x66; // these are seed numbers if not selected right then the randomness is not good
WORD rnd_d1=0x5A; // these give fairly good results
WORD rnd_d2=0xC3;
WORD rnd()
    {
    rnd_d0^=rnd_d1|rnd_d2; // xor
    rnd_d1*=rnd_d2; // mul
    rnd_d2+=rnd_d1; // add
    rnd_d0=(rnd_d0<<8)|(rnd_d0>>8); // 8bit halves swap
    return rnd_d0;
    }

所以只使用来自 for (int y=0;y<ys;y++) for (int x=0;x<xs;x++) pyx[y][x]=0x00010101*int(rnd()>>8); 伪随机数的高8bit,乘法只是将这个16bit数转换为灰度颜色。

  • 8bit是图像大小
  • xs,ys是指向其线条的直接图像指针

如果没有在PC上进行适当的测试,请不要更改种子数

错误选择的种子导致完全没有随机性。如果你想安全地播种(不测试),那么使用提供的常量播种,然后调用pyx和你的新种子数一样多。现在就把这个搞得很好,所以可能会有更好的种子,这些只是我发现的第一个产生相当好结果的种子

这些种子也很好:

rnd()

以上是关于如何种子生成随机数?的主要内容,如果未能解决你的问题,请参考以下文章

如何种子生成随机数?

提升多精度随机生成器种子误差

生成随机种子十六进制颜色?

生成随机数的种子

Random类

就生成随机数而言,种子是啥? [复制]