发布网友 发布时间:2022-04-22 04:49
共2个回答
热心网友 时间:2023-06-23 11:08
给你一个超强例子: 欢迎到卡卡空间: http://hi.baidu.com/woodking 主 题: 线性叠加伪随机数函数 ; 关 键 词: 随机数,8位单片机,random,8 bit mcu ; 参考资料: 1.<> ; by Bruce Clark, 7 Jun 2004 ; 2.<> ; by Donald Knuth ; 8位单片机很多地方需要随机数,比如游戏的洗牌,可在timer中取数,但是随机数质 量不高。随机数是一个既简单又复杂的问题,这里的例子使用了众所周知的线性叠加法,没 有完美的方法产生随机数,不过线性叠加法是一个合适的方法,彻底解决8位机随机数的问 题。 伪随机数函数总是返回可预知的数字,像抛骰子,如果抛足够多次,那么我们得到了一 个足够长的数字序列, 3,1,5,1,4,6,5,4,6,5,4,5,6,1,3,2,1,6,4,6,5,4,3,2,1,3,2,1,4,2,3,1,3...... 如果从序列中一个接一个的取出数字,那么数字就看似随机。 问题的关键是从这序列的哪个点(数字)开始取数?这个开始的点(数字)叫做种子。 注意,如果从相同的点(种子)开始,将会得到相同的数字,这是因为我们是从固定的序 列中取数字(所以叫伪随机)。但这却是一个有用的特性,我们可以每次从不同的点取数,即 改变种子! 在6502上,8位或16位随机数是最常用的,函数返回一个32位的数字,范围0~2^32。名 词"线性叠加"听起来容易范晕, 其实只涉及二个内容:乘法和加法。三个步骤: 1. 为了取得新的种子(也就是从序列开始的那个点的数字),旧的种子和一个常数A相乘, 2. 所得结果然后和第二个常数c相加。 3. 新的种子是结果的低32位(记住,这个函数返回32位数字)。保留低32位很重要,用来获 得下一个种子。 计算公式: 种子 = A * 种子 + C 此公式在几何图中表示一条直线,而且新种子由旧种子反复相加得来,所以叫线性叠加。 随机数函数的关键在于选择优秀的"常数A"(也叫乘数A),其实也就是选择了一个固定 的数字序列。"常数c",不像乘数A那样重要,但是它一定是个奇数。事实上, c可选1,而 且这是例程所使用的,因为它会简化计算。 注意,奇数(旧的种子)乘奇数(乘数A)是奇数,再加奇数(常数c)将会是一个偶数;偶数 (旧的种子)乘奇数(乘数A),加奇数(常数c)将会是一个奇数。如此种子将会在奇数和偶数之 间转变。因为种子的变化足够随机,所以新种子的值可以作为8位或16位随机数。 子程序F_RandomSeed,计算 "种子 = 乘数 * 种子+1" (记得,c=1)。有三个版本: (1) 快速版本, 速度快,但占用Rom多。 (2) 兼顾版本,速度和占用Rom适中,空间和速度是在另外二个版本之间。 兼顾版B, 使用了另一个神奇的数字66066(10进制). (3) 最小版本,速度慢,但占用Rom小。 三个版本中使用的乘数1664525(10进制)=19660D(16进制),是从<<计算机程序的艺术, 第2册>>一书中选出,这是一个神奇的数字,经过论证和测试,这个数字对产生随机数至 关重要。想进一步研究的朋友可以阅读原著(参考资料2),书中以特别专业的数学方法讨论 了随机数问题。这里只是应用了其中的两个常数1664525(10进制)和69069(10进制),这里不 作讨论,因为篇幅问题是借口,其实自己没弄懂。 ;============================================================================== ; 快速版本 ;===================热心网友 时间:2023-06-23 11:08
对于51单片机里有两个定时器/计数器,可以利用其中的一个来产生随机数。但要设置成方式2,自己计数状态。这样,只有8位数。但不要开中断,只要计数就行。需要时就读一次定时器的低8位就行了。