45fan.com - 路饭网

搜索: 您的位置主页 > 网络频道 > 阅读资讯:随机数的产生原理是什么?

随机数的产生原理是什么?

2016-08-25 14:54:59 来源:www.45fan.com 【

随机数的产生原理是什么?

随机数的产生原理与实现

下载本节例子程序和源代码 (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

本文地址:http://www.45fan.com/a/question/67508.html
Tags: 产生 原理 随机数
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部