如何播种以生成随机数? [英] How to seed to generate random numbers?

查看:94
本文介绍了如何播种以生成随机数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

It does not generate the intended randomness.

我以为从$ 66的种子开始,然后将最后两个低位与xor进行异或运算,就可以得到下一个随机数,依此类推,但它只显示$ B3,并且完全没有变化.

I thought starting with a seed like $66 and xoring the two last lower bit and ror would give me the next random number and so on but it only shows $B3 and does not change at all.

我该如何喂食?上面的随机行显示了portc上的数字,因为我希望两个数字互相显示.

How am I meant to feed? The line above random displays the number on portc as I want two numbers displayed after each other.

我仅将AVR Studio 4用于1Mhz的atmega 8535.

I am only using 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平台:

After some searching through ancient asm source code archives of mine I found this for x86 MSDOS NASM platform I was using back in the days:

;.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上尝试查看随机性是否适合您的任务.

The idea is to have some stored number do some basic ALU operations like +,*,/,<<,>>,&,^ but ensure that no saturation occurs and usually swap of H,L of some value to keep the randomness in check. So port this to your asm but I strongly recommend to code it and try on PC first to see if the randomness is OK for your task.

顺便说一句,您还可以将程序存储器或任何ROM内容用作随机性的基础...这也利用了内部的 RTC 块,因此您必须省略该部分或添加计时器,或者只是而是遍历一堆非空数据.

BTW you can use also the program memory or any ROM content as base for randomness ... this is also exploiting the internal RTC block so you have to omit that part or add a timer or just loop through bunch of non empty data instead.

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

我发现了我的更老的名为NoSignal的演示(来自TASM的1997年),里面有rnd:

I found even older demo of mine called NoSignal (from 1997 in TASM) which have rnd inside:

    .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:

It fill screen and speaker with white noise as if no antenna cable in analog TV. This version is 44 Bytes long, pseudo random generator starts at label l0:

  • ax是生成的数字(也是以前生成的数字,例如temp)
  • di正在增加(类似于实际时间)...
  • cl正在递减
  • ax is the generated number (and also the prevvious generated number like you temp)
  • di is incrementing (something like actual time)...
  • cl is decrementing

所以,如果我看对的话就足够了:

so if I look at it right it should be enough:

    rnd:ror ax,cl       ;rnd...ax
        add ax,di
        inc di
        dec cl
        ret

并添加push/pop如果需要的话,存储寄存器/值.如果您需要更复杂的功能,请使用模质数算法.

and add push/pop store the registers/values if needed. If you need something more sophisticated then use modulo prime arithmetics.

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

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;
    }

上述随机生成器已被限制为 DOS 环境时间或特殊用途.这不是……随机性是这样的:

The above random generators was tighted to DOS environment time or special usage. This one is not ... the randomness is like this:

当我用它填充NoSignal图像窗口时,结果是这样的:

when I use it to fill NoSignal image window the result is this:

以及此处的 Gif 动画:

NoSignal填充代码如下:

The NoSignal fill code is as this:

 for (int y=0;y<ys;y++)
  for (int x=0;x<xs;x++)
   pyx[y][x]=0x00010101*int(rnd()>>8);

因此,使用了16bit伪随机数中的较高的8bit,乘法运算只是将8bit数转换为灰度颜色.

So just high 8bit from the 16bit pseudo random number is used the multiplication just converts this 8bit number to gray-scale color.

  • xs,ys是图像大小
  • pyx是指向其行的直接图像指针
  • xs,ys is image size
  • pyx is the direct image pointer to its lines

未经PC上的正确测试,请勿更改种子编号

错误选择的种子完全不会导致随机性.如果要安全地播种(未经测试),请使用提供的常数播种,然后调用rnd()与您新的播种号一样多.现在已经解决了这个问题,因此可能会有更好的种子,这些只是我发现的第一个获得相当好的结果

Wrongly selected seeds leads to no randomness at all. If you want to safely seed (without testing) then seed with provided constants and then call rnd() as much times as the new seed number of yours is. Busted this right now so there may be better seeds for this, these are just the first ones I found that gives fairly good results

这些种子也不错:

    WORD rnd_d0=0x37A6;
    WORD rnd_d1=0x377A;
    WORD rnd_d2=0x3BC3;

这篇关于如何播种以生成随机数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆