⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 randomicity.txt

📁 8位单片机很多地方需要随机数
💻 TXT
📖 第 1 页 / 共 3 页
字号:
         CLC 	       		; 加上种子,保存高8位到A
         TAX 	
         LDA 	R_Temp
         ADC 	R_Seed0
         STA 	R_Temp
         LDA 	R_Temp+1
         ADC 	R_Seed1
         STA 	R_Temp+1
         LDA 	R_Temp+2
         ADC 	R_Seed2
         STA 	R_Temp+2
         TXA 	
         ADC 	R_Seed3
L_R8B   
	 ROR 	       		; 乘积右移
         ROR 	R_Temp+2
         ROR 	R_Temp+1
         ROR 	R_Temp
         LSR 	R_Mod    	; 直到所有8位的R_Mod已经循环移出
         BNE 	L_R8A
         RTS

    这里是任意16位随机数版本,F_RandomSeed16
    
;==============================================================================
; 线性叠加伪随机数函数
; 取得下一个种子并且获得来自它的一个16位的随机数
; 需要F_RandomSeed子程序
;-------------------------------------------------------------------------------
; 输入:
;   R_Mod,R_Mod+1 <--- 随机数范围
; 输出:
;   R_Rnd,R_Rnd+1 ---> 0 <= 随机数 < R_Mod+1,R_Mod
; 重写
;   R_Temp 
;===============================================================================
F_Random16 
	 JSR 	F_RandomSeed	; 取得下个种子
         LDA 	#0    		; 种子乘R_Mod
         STA 	R_Rnd+1
         STA 	R_Rnd
         STA 	R_Temp
         LDY 	#16
L_R16A   LSR 	R_Mod+1		; 移出R_Mod,将循环16次
         ROR 	R_Mod
         BCC 	L_R16B		; 如果c=0,分支
         CLC 	      		; 加上种子,保存乘积高16位到R_Rnd,R_Rnd+1
         ADC 	R_Seed0
         TAX 	
         LDA 	R_Temp
         ADC 	R_Seed1
         STA 	R_Temp
         LDA 	R_Rnd
         ADC 	R_Seed2
         STA 	R_Rnd
         LDA 	R_Rnd+1
         ADC 	R_Seed3
         STA 	R_Rnd+1
         TXA 	
L_R16B   ROR 	R_Rnd+1		; 乘积右移
         ROR 	R_Rnd
         ROR 	R_Temp
         ROR 	
         DEY 	
         BNE 	L_R16A
         RTS
	
    因为种子有2^32可能的值,当范围是2^n(n=1,2,3,..,32)时,所有的可能值,产生的几
率均等,然而,用6举例来说,却存在非常小的几率不均等性,因为 2^32 不是 6 的倍数。
但是 2^32 - 4 是 6 倍数,解决的方法是,剔除种子的四个值,再次调用F_RandomSeed。因
因为只有四个值从 2^32中剔除,它的可能性十分小,最多二次连续的种子值被剔除,调用
两次F_RandomSeed。优秀的数字序列确实如此。 
   问题是剔除哪4个值?为了要回答这一问题, 一个较简单的例子,4位的种子,范围上限=7,调用
16-2次F_RandomSeed后表现出多样性。 因为只有16种可能的值,所有的列出了所有的数,
连同对应的 种子*范围上限 一起。

       种子  种子*7
       ---- --------
       0000 000 0000 --->剔除
       0001 000 0111 --->
       0010 000 1110 --->
       0011 001 0101
       0100 001 1100
       0101 010 0011
       0110 010 1010
       0111 011 0001 --->剔除
       1000 011 1000 --->
       1001 011 1111 --->
       1010 100 0110 
       1011 100 1101
       1100 101 0100
       1101 101 1011
       1110 110 0010
       1111 110 1001
             ^
             |
             随机数0~6
    
    上面的随机数高3位(种子*范围上限),0和3发生三次,而且其余发生两次。 注意低4位(种子
*范围上限),当高3位是 000 或 011,低4位小于2的种子剔除。有二个方法决定种子的取舍
    (a)如果 种子低位*范围上限 小于种子值,剔除此数字,
或者
    (b)如果 低位大于或等于16-种子值,剔除此数。

    后者因为它能更快速地被实现,所以使用次方法。对于 32 位的情形,检查种子的低
32位*范围上限的乘积 是否小于 (2^32-种子),判断是否剔除。 

    唯一的剩余问题是, 多少种子值应该被剔除? 这能由 2^32/范围上限(随机数范围)计算。除
法的余数就是要剔除的种子数。

    这部分的子程序返回的随机数几率均衡,所以叫 F_URandom 。返回的随机数,R_Rnd,
范围0<= R_Rnd< R_Mod 之间。 有二个版本, (1)对于8位的R_Rnd和R_Mod,(2)对于16位
的R_Rnd和R_Mod。 

    8位的版本,叫做 F_URandom8
;==============================================================================
; 伪随机数函数的线性叠加
; 取得下种子并且获得来自它的8位随机数
; 需要F_RandomSeed子程序
;------------------------------------------------------------------------------
; 输入:
;   A <--- 随机数范围
; 输出:
;   A ---> 随机数 0<= 随机数 < 范围
; 重写
;   R_Mod,R_Rem,R_Temp,R_Temp+1,R_Temp+2,R_Temp+3
;===============================================================================
F_URandom8 
	 STA 	R_Mod 		; 保存随机数范围
         LDX 	#32		; 计算 2^32/R_Mod的余数
         LDA 	#1
         BNE 	L_UR8B
L_UR8A   ASL 	      		; 被除数左移
         BCS 	L_UR8C		; c=1 分支
L_UR8B   CMP 	R_Mod
         BCC 	L_UR8D		; 如果部分被除数 <R_Mod 分支
L_UR8C   SBC 	R_Mod 		; 减去R_Mod
L_UR8D   DEX 	
         BPL 	L_UR8A
         STA 	R_Rem		; 保存余数到R_Rem
L_UR8E   JSR 	F_RandomSeed
         LDA 	#0    		; 种子*R_Mod
         STA 	R_Temp+3
         STA 	R_Temp+2
         STA 	R_Temp+1
         STA 	R_Temp
         LDY 	R_Mod 		; 保存R_Mod到Y
         SEC 	
         ROR 	R_Mod 		; 右移一位(循环8次)
L_UR8F   BCC 	L_UR8G		; c=0 ,分支
         CLC 	      		; 加种子到R_Temp
         TAX 	
         LDA 	R_Temp
         ADC 	R_Seed0
         STA 	R_Temp
         LDA 	R_Temp+1
         ADC 	R_Seed1
         STA 	R_Temp+1
         LDA 	R_Temp+2
         ADC 	R_Seed2
         STA 	R_Temp+2
         LDA 	R_Temp+3
         ADC 	R_Seed3
         STA 	R_Temp+3
         TXA 	
L_UR8G   ROR 	R_Temp+3	; 乘积右移
         ROR 	R_Temp+2
         ROR 	R_Temp+1
         ROR 	R_Temp
         ROR 	
         LSR 	R_Mod 		; 直到所有8位的R_Mod都移出
         BNE 	L_UR8F
         CLC 	      		; 把余数加入乘积
         ADC 	R_Rem
         BCC 	L_UR8H		; 如果没有8位进位,分支
         INC 	R_Temp		; 乘积字节1 加1
         BNE 	L_UR8H		; 如果没有16位进位,分支
         INC 	R_Temp+1	; 乘积字节2 加1
         BNE 	L_UR8H		; 如果没有24位进位,分支
         INC 	R_Temp+2	; 乘积字节2 加1
         STY 	R_Mod 		; 保存R_Mod (不影响Z标志!)
         BEQ 	L_UR8E		; 如果32位进位,分支
L_UR8H   LDA 	R_Temp+3	; 乘积高8位,返回A
         RTS
    
    这里是 F_URandom 的 16 位版本,叫做了 F_URandom16。
;==============================================================================
; 伪随机数函数的线性叠加
; 取得下种子并且获得来自它的16位的随机数
; 需要F_RandomSeed子程序
;------------------------------------------------------------------------------
; 输入:
;   MOD=modulus
; 输出:
;   R_Rnd= random number,0<= R_Rnd< R_Mod
; 重写
; R_RemH,R_RemL,TEMP,R_Temp,R_Temp+1,R_Temp+2 和 R_Temp+3
;==============================================================================
F_URandom16
         LDX 	#32		; 计算 2^32/R_Mod
         LDA 	#0
         STA 	R_RemH
         SEC 	     		; 准备移位
L_UR16A  ROL 	      		; 被除数左移
         ROL 	R_RemH
         BCS 	L_UR16B		; 如果移出1,分支
         TAY 	      		; 比较部分被除数和R_Mod
         CMP 	R_Mod
         LDA 	R_RemH
         SBC 	R_Mod +1
         TYA 	
         BCC 	L_UR16C		; 如果部分被除数 <R_Mod,分支
L_UR16B  SBC 	R_Mod 		; 减去R_Mod (计算余数)
         TAY 	
         LDA 	R_RemH
         SBC 	R_Mod +1
         STA 	R_RemH
         TYA 	
         CLC 	
L_UR16C  DEX 	
         BPL 	L_UR16A
         STA 	R_RemL 		; 储存余数低字节 R_Rem
         LDA 	R_Mod +1	; 储存R_Mod高字节
         STA 	TEMP
L_UR16D  JSR 	F_RandomSeed
         LDA 	R_Mod 		; 储存R_Mod低字节到R_Temp+3
         STA 	R_Temp+3
         LDA 	#0    		; 种子乘R_Mod
         STA 	R_Rnd+1
         STA 	R_Rnd
         STA 	R_Temp+2
         STA 	R_Temp+1
         LDY 	#16
L_UR16E  LSR 	R_Mod+1		; 右移
         ROR 	R_Mod
         BCC 	L_UR16F		; 如果零被移出,分支
         CLC 	      		; 增加种子,保存乘积高16位到 R_Rnd
         TAX 	
         LDA 	R_Temp+1
         ADC 	R_Seed0
         STA 	R_Temp+1
         LDA 	R_Temp+2
         ADC 	R_Seed1
         STA 	R_Temp+2
         LDA 	R_Rnd
         ADC 	R_Seed2
         STA 	R_Rnd
         LDA 	R_Rnd+1
         ADC 	R_Seed3
         STA 	R_Rnd+1
         TXA 	
L_UR16F  ROR 	R_Rnd+1		; 乘积右移
         ROR 	R_Rnd
         ROR 	R_Temp+2
         ROR 	R_Temp+1
         ROR 	R_Temp
         ROR 	
         DEY 	
         BNE 	L_UR16E
         CLC 	      		; 把余数加入乘积
         ADC 	R_RemL
         LDA 	R_Temp
         ADC 	R_RemH
         BCC 	L_UR16G		; 如果没有16位进位,分支
         INC 	R_Temp+1	; 乘积的字节2,加1
         BNE 	L_UR16G		; 如果没有24位进位,分支
         LDA 	R_Temp+3	; 保存R_Mod
         STA 	R_Mod
         LDA 	TEMP
         STA 	R_Mod +1
         INC 	R_Temp+2	; 乘积的字节3,加1
         BEQ 	L_UR16D		; 如果32位进位,分支
L_UR16G  RTS
;=============================================================================
    
    8位单片机随机数问题解决了,但是新的问题又来了,
    
 1. 因为最初开始的种子是 00000000hex,刚开始几次的随机数不理想,调用多少次后,随
    机数才表现出理想效果? (4 bit 16-2次后,32bit 多少次后?)
    
 2. 两个神奇的数字,1664525(10进制)和69069(10进制)是如何得到的?用这个数产生的数
    字序列是否是最完美的?是否有更完美的数字?如何得出?
 
 3. 种子从00000000hex开始,调用多少次F_RandomSeed后,种子是否可以回到00000000hex?
    种子从00000000hex开始,调用2^32次后,种子回零,是否有这样的神奇系数和列表?
 
    理论上,使用例子的最快版本,调用F_RandomSeed 2^32次,用4M 主频单片机,0.5uS
一条指令速度,全速运行,大约需要56.07小时。以上的例子都经过6502 simulator V1.1.9.21
测试。最多运行了40分钟,没有发现种子全部回零。

    有人能够论证或测试以上的问题吗?

    喂!数学或编程的各路英雄,谁敢接招?
    
;--------------------------------------------------------------------------------
; end of the file 2006-09-23
;--------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -