随机数的产生原理与实现

漫谈C语言随机数 来说说C语言如何产生随机数。 有人会说这不简单?time() + srand() + rand() 3个函数不就OK了吗? 是的,不过,我们还是来看看原理比较好,也就是随机数是如何产生的。 这不无聊。C本来就不是一门太高级的语言。这句话并不是贬义的。 首先,我要说的是:计算机本身是不能产生随机数的。 计算机再如何先进,终究是一部机器。它没有逻辑思维,只会计算,却不懂怎样算,怎么能产生 阅读详情

随机数的产生原理与实现 
 
下载本节例子程序和源代码 (3.91 KB)

随机数的产生在病毒中占有十分重要的地位,尤其是在变形引擎中,没有它就不成事了……因此,今天就让我们来探讨一下如何产生一个随机数。

首先值得说明的是,要产生一个随机数,方法有很多种,例如混沌和分形理论(原理比较复杂,但是公式却异常简单,将来有空的话我会介绍一下)……但是这些方法的缺点是计算难度大,需要花费的时间多,有没有一种实现起来比较简单的方法呢?

答案是肯定的。我们先来看一条数学公式:

Rand_Number = (Rand_Seed * X + Y) mod Z

利用这条公式,我们就可以生成一个伪随机数了。可是为什么是“伪随机数”呢?因为实际上要保证每次生成的随机数都不同,那是不太可能的,我们唯一能做到的只能是尽量使每次生成的数字与前面的不同,并且尽量使生成的数字均匀分布在指定的范围内。

上面的这条公式就能满足这两点。至于为什么……呵呵,我也不懂,因为它牵涉到十分复杂的数学求证过程,我们只需要知道如何应用就成了:

Rand_Seed 表示随机数种子,注意这个“种子”必须每次都不同,我们可以简单地利用 GetTickCount() 这个 API 来获得不同的数字,当然,你也可以用别的方法来取得,例如读取当前鼠标的坐标等等……

X、Y必须至少有一个为素数。什么叫素数?Hoho,让我们来翻翻小学课本……素数就是除了 1 和它本身,不能被其他数整除的数字。在这里我们可以简单地给 X、Y 赋值 23 和 7 ,其实别的素数也行,我只是随便取了这两个数字。

最后,Z 也应该是一个素数,这样才能保证产生的随机数能得到上限的值。不过我在实践中发现,这个 Z 不一定要准确地为素数。Why? I also don’t know...

总结一下,利用以上的公式,我们可以编写汇编代码如下:

iRand   proc uses ecx edx first:DWORD, second:DWORD
   invoke GetTickCount ; 取得随机数种子,当然,可用别的方法代替
   mov ecx, 23         ; X = ecx = 23
   mul ecx             ; eax = eax * X
   add eax, 7          ; eax = eax + Y (Y = 7)
   mov ecx, second     ; ecx = 上限
   sub ecx, first      ; ecx = 上限 - 下限
   inc ecx             ; Z = ecx + 1 (得到了范围)
   xor edx, edx        ; edx = 0
   div ecx             ; eax = eax mod Z (余数在edx里面)
   add edx, first      ; 修正产生的随机数的范围
   mov eax, edx        ; eax = Rand_Number
   ret
iRand   endp

然后用以下语句调用:

invoke iRand, 1, 100

这样就产生了一个在 1 和 100 之间的随机数啦。

是不是很简单呢?最后我再给出一个利用本代码的例子,演示如何生成随机数:

;*********************************************************
;程序名称:随机数的产生原理与实现
;作者:罗聪
;日期:2002-11-21
;出处:http://www.LuoCong.com(老罗的缤纷天地)
;注意事项:如欲转载,请保持本程序的完整,并注明:
;转载自“老罗的缤纷天地”(http://www.LuoCong.com)
;*********************************************************

.386
.model flat, stdcall
option casemap:none

include /masm32/include/windows.inc
include /masm32/include/kernel32.inc
include /masm32/include/user32.inc
includelib /masm32/lib/kernel32.lib
includelib /masm32/lib/user32.lib

WndProc         proto :DWORD, :DWORD, :DWORD, :DWORD
iRand           proto :DWORD, :DWORD

.const
IDC_BUTTON_GENERATE equ 3000
IDC_EDIT_FIRST      equ 3001
IDC_EDIT_SECOND     equ 3002

.data
szDlgName           db  "lc_dialog", 0
szCaption           db  "Rand Number Generator by LC", 0
szText              db  255 dup(0)
szTemplate          db  "(%d ~ %d)随机数:", 13, 10, 13, 10,/
                       "         %d", 13, 10, 13, 10,/
                       "老罗的缤纷天地", 13, 10,/
                       "http://www.LuoCong.com", 0
nFirst              dd  0
nSecond             dd  0

.code
main:
   invoke GetModuleHandle, NULL
   invoke DialogBoxParam, eax, offset szDlgName, 0, WndProc, 0
   invoke ExitProcess, eax

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
   LOCAL hEdit: HWND

   .if uMsg == WM_CLOSE
       invoke EndDialog, hWnd, 0
      
   .elseif uMsg == WM_COMMAND
       mov eax, wParam
       mov edx, eax
       shr edx, 16
       movzx eax, ax
       .if edx == BN_CLICKED
           .if eax == IDCANCEL
               invoke EndDialog, hWnd, NULL
           .elseif eax == IDC_BUTTON_GENERATE || eax == IDOK
               ;获得上限:
               invoke GetDlgItemInt, hWnd, IDC_EDIT_FIRST, NULL, TRUE
               mov nFirst, eax
               ;获得下限:
               invoke GetDlgItemInt, hWnd, IDC_EDIT_SECOND, NULL, TRUE
               mov nSecond, eax
               ;产生随机数:
               invoke iRand, nFirst, nSecond
               ;输出:
               invoke wsprintf, addr szText, addr szTemplate, nFirst, nSecond, eax
               invoke MessageBox, hWnd, addr szText, addr szCaption, MB_OK or MB_ICONINformATION
           .endif
       .endif
   .else
       mov eax, FALSE
       ret
   .endif
   mov eax, TRUE
   ret
WndProc endp

;**********************************************************************
; 函数功能:产生范围从 first 到 second 的随机数
; 传入参数:
;           first  = 下限
;           second = 上限
; 返回参数:
;           eax = Rand_Number
; 所用公式:
;           Rand_Number = (Rand_Seed * X + Y) mod Z
; 补充说明:
;           (1)本例中用 GetTickCount 来取得随机数种子,
;              在实际应用中,可用别的方法代替。
;           (2)要产生随机数,X和Y其中之一必须是素数,
;              所以 X = 23, Y = 7(可用别的素数代替)
;**********************************************************************
iRand   proc uses ecx edx first:DWORD, second:DWORD
   invoke GetTickCount ; 取得随机数种子,当然,可用别的方法代替
   mov ecx, 23         ; X = ecx = 23
   mul ecx             ; eax = eax * X
   add eax, 7          ; eax = eax + Y (Y = 7)
   mov ecx, second     ; ecx = 上限
   sub ecx, first      ; ecx = 上限 - 下限
   inc ecx             ; Z = ecx + 1 (得到了范围)
   xor edx, edx        ; edx = 0
   div ecx             ; eax = eax mod Z (余数在edx里面)
   add edx, first      ; 修正产生的随机数的范围
   mov eax, edx        ; eax = Rand_Number
   ret
iRand   endp

end main
;********************   over    ********************
;by LC

它的资源文件:

#include "resource.h"

#define IDC_BUTTON_GENERATE 3000
#define IDC_EDIT_FIRST      3001
#define IDC_EDIT_SECOND     3002
#define IDC_STATIC          -1

LC_DIALOG DIALOGEX 10, 10, 210, 60
style DS_SETFONT | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Rand Number Generator by LC, 2002-11-21"
FONT 8, "MS Sans Serif"
BEGIN
   LTEXT           "Please input the range below:", IDC_STATIC, 5, 5, 200, 10
   RTEXT           "From:", IDC_STATIC, 10, 20, 20, 10
   EDITTEXT        IDC_EDIT_FIRST, 30, 20, 70, 10, ES_AUTOHSCROLL | NOT WS_BORDER, WS_EX_STATICEDGE
   RTEXT           "To:", IDC_STATIC, 110, 20, 20, 10
   EDITTEXT        IDC_EDIT_SECOND, 130, 20, 70, 10, ES_AUTOHSCROLL | NOT WS_BORDER, WS_EX_STATICEDGE
   DEFPUSHBUTTON   "Generate(&G)", IDC_BUTTON_GENERATE, 70, 40, 50, 13, BS_FLAT | BS_CENTER
END


如果您还有什么疑问,或者发现了我的表述和理解有误,欢迎来信交流。lcother@163.net 
 
老罗于
2002-11-22 

  

利用计算机内部计数器生成真随机数原理及实现 一、手动产生随机数方法  计数器是精密器件不能直接产生随机数,但可以让其为产生随机数服务。每个计算机都有其工作频率称为主频,与之相对应的是时钟周期,下面的程序段DWORD n;_asm//嵌入汇编语言{rdtsc//读计数器值mov n,eax//计数器低位值进入n}  的作用是读取自开机以来CPU经历的时钟周期数的低32位数值(高位值变化缓慢在此无用)放到变量 n中,每调用一次 n的数值等于其现 阅读详情

相关推荐

《ZigBee开发笔记》第二部分 基础篇-第11章 CC2530随机数发生器

1 理论分析 1.1 CC2530 随机数发生器简介 随机数发生器有如下功能。  产生伪随机字节,可以被 CPU 读取,或由命令选通处理器直接使用。  计算写入到 RNDH 的 CRC16 字节。  由写入到 RNDL 的值播种。 随机数发生器是一个 16 位的线性反馈移位寄存器 LFSR,带有多项式 X 16 + X15 + X 2 +1(即 CRC16) 。根...

不问归期的博客 2894

随机数产生器

#include #include #include #define LOCAL int n=40000,m=100000; double random() { return (double)rand()/RAND_MAX; } int random(int m) { return (int)(random()*(m-1)+0.5); } int main(int

Carp_and_wind的专栏 573

系统辨识基础知识(1)——产生(0,1)均匀分布随机数的原理分析及MATLAB实现

通过计算机产生(0,1)均匀分布随机数的方法大致有三类: Rand的百万随机数【缺点:占用内存量大】 物理方法 【缺点:设备维护困难】 数学方法 【特点:产生速度快,占用内存小】 下面介绍利用数学方法产生(0,1)均匀分布随机数的方法。 利用数学方法实现(0,1)均匀分布随机数的本质是实现如下的递推运算: 每个(0,1)均匀分布的随机数总是前面各时刻随机数的函数,严格说来,上式的函数取任何形式都不可能产生真正的连续(0,1)均匀分布的随机数,因此,通常称用数学方法产生的(0,1)均匀分布的随机数叫做伪

Wendy的博客 4879

CC2530基础实验:(7)随机数的产生

本实验用于学习CC2530芯片:随机数的产生,介绍LFSR,CC2530产生随机数的过程。产生随机电压后通过串口发给上位机显示

李小风风风的博客 1849

C语言之实现随机数产生算法

随机数,也就是在不同的时刻产生不同的数值。在UNIX操作系统和window的操作系统上,我们知道有一个函数rand,它就是用来产生随机数的函数API接口,那么它的原理如何实现? 如果约定a1=f(seed),an+1=f(an),那么可以得到一个序列a1,a2,a3..an,那么要制作一个伪随机函数rand,只需要让它每调用一次就返回序列的下一个元素就行。其实就是相当于第1次调用rand返回a1

Bruce.yang的嵌入式之旅 1万+

FPGA设计中,产生LFSR伪随机数

今天给大侠带来在FPGA设计中,产生LFSR伪随机数,话不多说,上货。 一、概述 通过一定的算法对事先选定的随机种子(seed)做一定的运算可以得到一组人工生成的周期序列,在这组序列中以相同的概率选取其中一个数字,该数字称作伪随机数,由于所选数字并不具有完全的随机性,但是从实用的角度而言,其随机程度已足够了。 这里的“伪”的含义是,由于该随机数是按照一定算法模拟产生的,其结果是确定的,是可见的,因此并不是真正的随机数。伪随机数的选择是从随机种子开始的,所以为了保证每次得到...

3693

利用计算机可产生随机数,利用计算机内部计数器生成真随机数原理及实现

一、手动产生随机数方法计数器是精密器件不能直接产生随机数,但可以让其为产生随机数服务。每个计算机都有其工作频率称为主频,与之相对应的是时钟周期,下面的程序段DWORD n;_asm//嵌入汇编语言{rdtsc//读计数器值mov n,eax//计数器低位值进入n}的作用是读取自开机以来CPU经历的时钟周期数的低32位数值(高位值变化缓慢在此无用)放到变量 n中,每调用一次 n的数值等于其现有数值加...

weixin_33899835的博客 800

单片机随机数产生

单片机上可以执行的随机序列产生的代码,更易更换随机因子,做到真正的随机序列产生

JAVA产生指定范围的随机数

  《JAVA产生指定范围的随机数》  产生机制:                      产生Min-Max之间的数字  实现原理:                     Math.round(Math.random()*(Max-Min)+Min) long Temp; //不能设定为int,必须设定为long //产生1000到9999的随机数 Temp=Math.round(Math.

雄鹰国际 5598

用单片机产生随机数的两种方法

用单片机产生随机数的两种方法。

随机数产生原理及实现.docx

包含六种随机数产生方案及相关matlab代码的实现,均匀分布,泊松分布,几何分布,二项分布,指数分布,正态分布

关于随机数的产生

1.rand() rand() 的内部实现是用线性同余法做的,它不是真的随机数,因其周期特别长,故在一定的范围里可看成是随机的。 rand() 返回一随机数值的范围在 0 至 RAND_MAX 间。RAND_MAX 的范围最少是在 32767 之间(int)。用 unsigned int 双字节是 65535,四字节是 4294967295 的整数范围。0~RAND_MAX 每个数字被选中的机率是相同的。 用户未设定随机数种子时,系统默认的随机数种子为 1。 rand() 产生的是伪随机数字,每次执

guangod的博客 1037

FPGA篮球计分器:从需求分析到模块化实现的实战指南

本文详细介绍了FPGA篮球计分器的设计与实现,涵盖需求分析、模块化设计及实战调试。重点解析了24秒精确倒计时、12分钟比赛计时、比分统计和数码管显示等核心模块的Verilog实现,提供了按键消抖、状态机设计和BCD码处理等关键技术细节,帮助开发者掌握FPGA数字系统设计方法。

sql99的博客 218

随机数产生原理及应用

 摘要:         本文简述了随机数的产生原理,并用C语言实现了迭代取中法,乘同余法等随机数产生方法,同时,还给出了在符合某种概率分布的随机变量的产生方法。 关键词: 伪随机数产生,概率分布 1前言:        在用计算机编制程序时,经常需要用到随机数,尤其在仿真等领域,更对随机数的产生提出了较高的要求,仅仅使用C语言类库中的随机函数已难以胜任相应的工作。本文简单的介绍随

7044

Cartographer参数调优指南:如何用Lua配置解决建图漂移问题

本文深入解析Cartographer SLAM系统的Lua参数调优方法,针对建图漂移问题提供完整解决方案。从运动滤波、扫描匹配到多传感器融合,详细讲解关键参数配置技巧,并给出仓库物流和服务机器人等典型场景的优化方案,帮助开发者实现精准建图。

vulkan6gpu的博客 117

STM32驱动四位共阳极数码管实现高精度秒表计时器

本文详细介绍了如何使用STM32驱动四位共阳极数码管实现高精度秒表计时器。项目基于STM32F103C8T6最小系统板,通过定时器中断和GPIO控制,实现0.1秒精度的计时功能,并解析了共阳极数码管的动态扫描原理及按键消抖等关键技术。

n8m7b6v5c4的博客 951

C++中产生随机数

计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了。)    我们知道rand()函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准

纸上得来终觉浅 304

Eclipse在Mac上报错JNI_CreateJavaVM?可能是你的JDK架构搞错了(附Adoptium JDK下载指南)

本文深入解析了Mac(尤其是Apple Silicon芯片)上Eclipse启动时出现“JNI_CreateJavaVM”错误的根本原因,即JDK架构(aarch64与x86_64)不匹配。文章提供了详细的诊断步骤,并推荐通过下载并配置Eclipse Adoptium提供的aarch64版本JDK来彻底解决问题,同时附上清晰的配置指南。

weixin_29065659的博客 321

C++产生随机数

       转载出处:C++产生随机数 随机数        计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期

Change the world by program. 263

SC-FDMA

<br />SC-FDMA(Single-carrier Frequency-Division Multiple Access,單載波分頻多工),是LTE的上行鏈路的主流多址。<br />SC-FDMA是單波載(Single-carrier),與OFDMA相比之下具有的較低的PAPR(峰值/平均功率比,peak-to-average power ratio),比多載波的PAPR低1-3dB左右(PAPR是由于多載波在频域叠加引起)。更低的PAPR可以使行動終端(mobile terminal)在發送功效方面

jod的专栏 3299

Python 爬虫实战:arXiv 学术论文 PDF 批量下载(含反爬策略与文件命名规范)

arXiv 是全球最大的免费开放预印本论文平台之一,涵盖物理学、数学、计算机科学等多个学科领域。研究人员、学生和工程师常常需要批量下载论文 PDF 进行文献综述、构建机器学习数据集或进行文本挖掘研究。然而,手动逐篇下载论文效率低下,因此开发一个自动化批量下载工具显得尤为重要。

yansideyucsdn的博客 1818

产生随机数

对于随机数,大家都知道,计算机不可能产生完全随机的数字,所谓的随机数发生器都是通过一定的算法对事先选定的随机种子做复杂的运算,用产生的结果来近似的模拟完全随机数,这种随机数被称作伪随机数。伪随机数是以相同的概率从一组有限的数字中选取的。所选数字并不具有完全的随机性,但是从实用的角度而言,其随机程度已足够了。伪随机数的选择是从随机种子开始的,所以为了保证每次得到的伪随机数都足够地“随机”,随机种子的

lxs5i5j的专栏 700

《AgentScope-Java 深入浅出教程》第10章 RAG 知识检索

RAG(Retrieval-Augmented Generation,检索增强生成)是一种将信息检索与文本生成相结合的技术架构。它通过从外部知识库中检索相关文档,将检索到的信息作为上下文注入到语言模型的提示中,从而增强模型的回答质量。│ RAG 工作流程 ││ ││ 用户问题 向量检索 上下文增强 生成回答 ││ ▼ ││ │ A │ ││ ││ 1. 接收问题 ││ 2. 将问题转换为向量,在知识库中检索相似文档 ││ 3. 将检索到的文档作为上下文添加到提示词中 │。

步子哥的博客 462

C/C++随机数的产生

计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了。) 我们知道rand()函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公

tkp2014的专栏 560

2025_NIPS_Truthful Aggregation of LLMs with an Application to Online Advertising

大型语言模型(LLMs)生成内容的 revenue 变现是在线广告的下一个前沿领域。我们考虑这样一种场景:广告商旨在影响LLM的回复,而平台则寻求最大化广告商价值并确保用户满意度。核心挑战在于,广告商的偏好通常与用户偏好存在冲突,且广告商可能误报其偏好。为解决这一问题,我们提出MOSAIC——一种拍卖机制,它确保真实申报是广告商的占优策略,并使每个广告商的效用与其对社会福利的贡献保持一致。重要的是,该机制无需LLM微调或访问模型权重,且随着计算资源的增加,可证明收敛到最优微调LLM的输出。

c_cpp_csharp的专栏 82

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

上一篇: 好书推荐:《价格理论》
下一篇: 随机数生成器
Simbao
博客等级 码龄24年 13粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值