当前位置:编程学习 > VB >>

vb是随机函数rnd和Randomize内部原理是什么?

我想知道VB的RND和Randomize的内部原理,到处也找不到答案。

有哪位高手能告诉我下?或者帮我解释一下下面我找到的类似东西?

【1】----------------------------
以下是我在网上找到的,网址:http://promiseforever.com/2009/04/18/vb-rnd-sorce.html
[vb]RND随机数的原理
Microsoft Visual Basic RND 函数中的伪随机数字生成使用线性congruential算法。
下面的伪代码文档使用的算法:
x0 = ( x0 * a + c ) MOD (2^24)
位置:

x0 = 以前的值 (初始值为327680)
a = 1140671485
c = 12820163

套用公式后,返回的整数的余数就是我们的随机数了。
表达式 x1/(2^24)将返回介于0.0到由RND函数返回的1.0之间的浮点数。
在VB内部无法实现这一运算,因为VB内部不支持无符号长整形数据。

下面的 C/C++ 代码可生成Visual Basic 生成的伪随机数字的前十个:

C#include "stdafx.h"   

int main(int argc, char* argv[])   
{   
unsigned long       rndVal;   
  
rndVal = 0x50000L;   
int i;   
float rndFloat;   
  
for (i=0;i<10;i++)   
 {   
 rndVal = (rndVal * 0x43fd43fdL + 0xc39ec3L) & 0xffffffL;   
 rndFloat = (float)rndVal / (float)16777216.0;   
 printf("Value is %.15f
",rndFloat);   
 }   
return 0;   
}
*********************************
我不会C
以下是我自己用javascript做的
<script type="text/javascript">
{
x0=327680
for (i=0;i<10;i++)

x0=(x0*1140671485+12820163) %(Math.pow(2,24))
x2=x0/(Math.pow(2,24))
document.write(x0)
document.write("<br/>")
document.write(x2)
document.write("<br/>")
}
}
</script>
可是结果和VB产生的随机数不一样,前2个一样,后8个不一样
javascritp产生的是:
11837123
0.7055475115776062
8949372
0.5334241390228271
9364304
0.5581560134887695
8926420
0.5320560932159424
12013640
0.7160687446594238
1625580
0.09689211845397949
6808831
0.4058379530906677
6466502
0.385433554649353
15348593
0.9148474335670471
6031472
0.35950374603271484

VB产生的是:
.705547511577606 .533424019813538 .579518616199493 .289562463760376 .301948010921478 .774740099906921 .014017641544342 .76072359085083 .814490020275116 .709037899971008 
不知道为什么,我哪里做错了?

------------------------------------
【2】以下也是网上找到的,网址是:http://tieba.baidu.com/p/1076541926
**************************************
我电脑上装的是VB6,所以拿MSVBVM60.dll来分析。去掉部分次要的代码后,核心代码如下:
RandomNext:
...
mov ecx,[ebp+8] //将上一次的随机数传入ecx
imul ecx,ecx,2BC03
mov eax,FFC39EC3
sub eax,ecx //此时,eax的值就是产生的下一个随机数了
...

Randomize:
...
mov ecx,[esp+8] //将Randomize后的参数传入ecx
mov edx,ecx
and edx,FFFF
shr ecx,8
shl,edx,8
and ecx,FFFF00
xor edx,ecx
mov ecx,[eax+4] //将旧的种子数传入ecx
and ecx,FF0000FF
or edx, ecx //此时,edx的值就是新的种子数
...
************************************
汇编语言我不懂,能帮我解释一下吗?让我能用VB作这个?
----------------------------------------------------------
麻烦解答,谢谢。 --------------------编程问答-------------------- 继续问:
VB的RND(-1)产生机制是什么?一般RND(1)多少个数就重复了?
------------
这些很有用,否则大量数据的时候会产生重复序列,即使用了Randomize也没用。
不信你们随机产生1、0;好像3万多或者6万多就完全重复了(用了Randomize)。 --------------------编程问答-------------------- 算法产生的随机数都是伪随机数,想法不同,随机数序列不同,如果按空间展开,基数非常大的不重复数据,初值用于指定攫取随机数序列的哪段

2
VB rnd的初值含义为:
小于 0 每次都使用 number 作为随机数种子得到的相同结果。 
大于 0 序列中的下一个随机数。 
等于 0 最近生成的数。 
省略 序列中的下一个随机数。 
--------------------编程问答-------------------- http://www.m5home.com/bbs/thread-3225-1-1.html

给你推荐一个绿豆写的CryptGenRandom示例,随机度很好,我实际应用中比较多,没发现明显的重复,原理好象是利用当前系统的一些信息来做种子,比如CPU占用率,内存占用率什么的. --------------------编程问答--------------------
引用 2 楼 worldy 的回复:
算法产生的随机数都是伪随机数,想法不同,随机数序列不同,如果按空间展开,基数非常大的不重复数据,初值用于指定攫取随机数序列的哪段

2
VB rnd的初值含义为:
小于 0 每次都使用 number 作为随机数种子得到的相同结果。 
大于 0 序列中的下一个随机数。 
等于 0 最近生成的数。 
省略 序列中的下一个随机数。

这个是外部原理,大家都知道的。

引用 3 楼 myjian 的回复:
http://www.m5home.com/bbs/thread-3225-1-1.html

给你推荐一个绿豆写的CryptGenRandom示例,随机度很好,我实际应用中比较多,没发现明显的重复,原理好象是利用当前系统的一些信息来做种子,比如CPU占用率,内存占用率什么的.


其实知道了rnd和Randomize的内部原理,就是具体怎么计算出来的,就很容易做出来没有重复序列的随机数。 --------------------编程问答-------------------- "没有重复序列的随机数"
你搞错了把,既然是随机的,不会是没有重复的,这只是几率问题,如果你的随机数范围定在0和1之间,你看看是不是一直0101010101这样的下去,不会有11010010001这样的出现?
其实做这种随机数完全可以利用时间、内存状况、CPU状况的某些参数做基础来运算,其方法也简单,复杂点的就弄随机表,比如
1234567890abcdefghijk
abcdefghijk1234567890
1234abcdefghijk1567890
1234abc15678defgk90hij
...
然后通过时间、内存等信息随机选择一个弄随机表,然后再根据随机表出随机数,这种随机表可以按格式程序生成,也可以用某个文件的数据来产生随机数,看你爱怎么干了,但再怎么弄,随机就是随机,还是有可能有重复的数据出现的,这种几率与你随机数的范围有关。 --------------------编程问答-------------------- 这种问题,围观一下。
--------------------编程问答-------------------- http://wenku.baidu.com/view/48d78444b307e87101f696f2.html
百度一下就有很多,自己研究一下吧 --------------------编程问答--------------------
引用 5 楼 SupermanKing 的回复:
"没有重复序列的随机数"
你搞错了把,既然是随机的,不会是没有重复的,这只是几率问题,如果你的随机数范围定在0和1之间,你看看是不是一直0101010101这样的下去,不会有11010010001这样的出现?
其实做这种随机数完全可以利用时间、内存状况、CPU状况的某些参数做基础来运算,其方法也简单,复杂点的就弄随机表,比如
1234567890abcdefghij……


楼主的意思不是在乎重复,而是在乎于循环,即不用到外部种子的情况下,随机数列会在某个地方出现循环。
当然,利用时间作种子就行了,VB.net的随机数就是利用了时间种子
--------------------编程问答-------------------- 是不是我写的太多了,各位老师都看不下去了,就给我回答。

其实我就想问:VB的RND 和Randomize是怎么算出来的。RND(n)的算法已经有了(我的帖子里有算法),但我不知道RND(-n)是怎么算的,也不知道Randomize(n)怎么算的。我的目的是随便给你个rnd(-n)和Randomize(n)你就能给我算出来结果是多少
我写的东西是前人研究的结果,想必各位老师也未必知道这些,仔细看下去很有收益。

我不是问重复序列的问题,也不是问随机数的原理(这些我都看了很多)。

麻烦各位老师能仔细看过我的贴在回答,谢谢。 --------------------编程问答--------------------
引用 9 楼 oGanTongShenShou 的回复:
是不是我写的太多了,各位老师都看不下去了,就给我回答。

其实我就想问:VB的RND 和Randomize是怎么算出来的。RND(n)的算法已经有了(我的帖子里有算法),但我不知道RND(-n)是怎么算的,也不知道Randomize(n)怎么算的。我的目的是随便给你个rnd(-n)和Randomize(n)你就能给我算出来结果是多少
我写的东西是前人研究的结果,想必……


到MSDN问吧   CSDN问不到结果的  --------------------编程问答-------------------- 我记得我上学那会也问过老师,老师说是根据时间,时间一直在变,随出来的数就一直在变,但是如果非要追根究底的话,这些理论是还是可以查出规律的。我这是或许是胡言乱语。 --------------------编程问答-------------------- 随机数有序列,但是不会有循环。
尽管rnd(1)在执行很多数次后可能会出现序列一样,但是这种极其2的情况不会有人去用,一般都会初始化一下。

说明

Rnd 函数返回小于 1 但大于或等于 0 的值。

number 的值决定了 Rnd 生成随机数的方式。

对最初给定的种子都会生成相同的数列,因为每一次调用 Rnd 函数都用数列中的前一个数作为下一个数的种子。


就算3万次后出现重复序列,前一个数相同的概率在3万分之一,一直到3万个数,它们是相乘的关系。你算一下3万个数的完全重复的概率……

第一次rnd(1)=0.6874239;下一次出现rnd(1)=0.6874239的概率是3万分之一;
第二次rnd(0.6874239)=0.8929685 ,下一次出现rnd(0.6874239)=0.8929685的概率是3万分之一
…… --------------------编程问答-------------------- 仅供参考
C:\Program Files\Microsoft Visual Studio 10.0\VC\crt\src\rand.c
/***
*rand.c - random number generator
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       defines rand(), srand() - random number generator
*
*******************************************************************************/

#include <cruntime.h>
#include <mtdll.h>
#include <stddef.h>
#include <stdlib.h>

/***
*void srand(seed) - seed the random number generator
*
*Purpose:
*       Seeds the random number generator with the int given.  Adapted from the
*       BASIC random number generator.
*
*Entry:
*       unsigned seed - seed to seed rand # generator with
*
*Exit:
*       None.
*
*Exceptions:
*
*******************************************************************************/

void __cdecl srand (
        unsigned int seed
        )
{
        _getptd()->_holdrand = (unsigned long)seed;
}


/***
*int rand() - returns a random number
*
*Purpose:
*       returns a pseudo-random number 0 through 32767.
*
*Entry:
*       None.
*
*Exit:
*       Returns a pseudo-random number 0 through 32767.
*
*Exceptions:
*
*******************************************************************************/

int __cdecl rand (
        void
        )
{
        _ptiddata ptd = _getptd();

        return( ((ptd->_holdrand = ptd->_holdrand * 214013L
            + 2531011L) >> 16) & 0x7fff );
}
--------------------编程问答-------------------- 随机必然有重复,所谓“不重复的随机”实际上是洗牌,洗牌算法参考下面:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int d[6];
int i,n,a,b,t;
int c,j;
void main() {
    srand(time(NULL));
    printf("shuffle 0..n-1 demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=0;i<n;i++) d[i]=i;/* 填写0~n-1 */
            for (i=n;i>0;i--) {/* 打乱0~n-1 */
                a=i-1;b=rand()%i;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=0;i<n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
    printf("shuffle 1..n demo\n");
    for (n=1;n<=5;n++) {/* 测试1~5个元素 */
        printf("_____n=%d_____\n",n);
        j=1;
        for (c=1;c<=n;c++) j=j*c;/* j为n! */
        j*=n*2;
        for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
            for (i=1;i<=n;i++) d[i]=i;/* 填写1~n */
            for (i=n;i>1;i--) {/* 打乱1~n */
                a=i;b=rand()%i+1;
                if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
            }
            printf("%04d:",c);
            for (i=1;i<=n;i++) printf("%d",d[i]);
            printf("\n");
        }
    }
}

大随机数参考下面:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
unsigned long ulrand(void) {
    return (
     (((unsigned long)rand()<<24)&0xFF000000ul)
    |(((unsigned long)rand()<<12)&0x00FFF000ul)
    |(((unsigned long)rand()    )&0x00000FFFul));
}
int i;
unsigned long ul;
void main() {
    srand(time(NULL));
    for (i=0;i<10;i++) {
        ul=ulrand();
        printf("%010lu 0x%08x\n",ul,ul);
    }
}
//2337588057 0x8b54c359
//1977377429 0x75dc6295
//3607316769 0xd7034921
//0009828482 0x0095f882
//3350859779 0xc7ba1003
//0945794621 0x385fae3d
//3400869024 0xcab524a0
//3097846779 0xb8a563fb
//4287421124 0xff8cdac4
//3934016258 0xea7c5302
补充:VB ,  基础类
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,