| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4976 人关注过本帖, 6 人收藏
标题:窗体间传值及随机数生成器小记
只看楼主 加入收藏
xiaoca324
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2008-8-27
收藏
得分:0 
good posting! thx so much
2008-10-06 06:59
梦心
Rank: 4
来 自:福建平和
等 级:贵宾
威 望:13
帖 子:1910
专家分:0
注 册:2007-5-11
收藏
得分:0 
下載下來學習學習!

我清高和我骄傲的倔强,在风中大声的唱:我不听,我不听~~做我自己最特别,呼呼~~啦啦~~~
我的博客园地址: [url]http://[/url]
2008-10-06 12:40
hellson
Rank: 2
来 自:北京
等 级:新手上路
威 望:4
帖 子:195
专家分:0
注 册:2008-9-1
收藏
得分:0 
以前随机数用起来没想这么多
程序代码:
               //byte[] bytes = new byte[4];
               //System.Security.Cryptography.RNGCryptoServiceProvider rng = 
               //    new System.Security.Cryptography.RNGCryptoServiceProvider( );
               //rng.GetBytes( bytes );
               //random = new Random(BitConverter.ToInt32( bytes , 0 ));[

春了夏了秋冬了,来了来了又来了
相信我的帖子打开都很快,看我头像就知道了
2008-10-06 13:26
zhangjun039009
Rank: 2
等 级:论坛游民
帖 子:60
专家分:10
注 册:2008-10-16
收藏
得分:0 
回复 1# 小仙 的帖子
好东西,收藏起来~~
2008-10-22 14:25
maibarry
Rank: 1
等 级:新手上路
帖 子:54
专家分:7
注 册:2008-10-21
收藏
得分:0 
非常好的文章
2008-10-22 16:58
铲铲
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:34
帖 子:506
专家分:0
注 册:2006-5-2
收藏
得分:0 
小仙,
关于:2.无参数的时候,以时间为种子值,不同时刻的数组都不相同,所以不必实例几个Random出来。但是要使用时错开时间制造一个时差。
这个地方有一点值得商榷。要使用随机数时,不必每次使用前都初始化Random对象实例,这个是对的。不过第二个,如果理解为:以一个时间差顺次初始化多个Random对象,所产生的随机数仍然有问题。

用Reflector来反查Random的方法,可以看到,Random的默认构造函数调用其带参的构造函数,传入参数是Environment.TickCount,表示系统从启动到现在所经过的毫秒数。

public Random() : this(Environment.TickCount)
{
}

我们再看带参数的构造函数:

public Random(int Seed)
{
    this.SeedArray = new int[0x38];
    int num2 = 0x9a4ec86 - Math.Abs(Seed);
    this.SeedArray[0x37] = num2;
    int num3 = 1;
    for (int i = 1; i < 0x37; i++)
    {
        int index = (0x15 * i) % 0x37;
        this.SeedArray[index] = num3;
        num3 = num2 - num3;
        if (num3 < 0)
        {
            num3 += 0x7fffffff;
        }
        num2 = this.SeedArray[index];
    }
    for (int j = 1; j < 5; j++)
    {
        for (int k = 1; k < 0x38; k++)
        {
            this.SeedArray[k] -= this.SeedArray[1 + ((k + 30) % 0x37)];
            if (this.SeedArray[k] < 0)
            {
                this.SeedArray[k] += 0x7fffffff;
            }
        }
    }
    this.inext = 0;
    this.inextp = 0x15;
    Seed = 1;
}

它是用一个确定的数,减去你所给种子的绝对值。作为含有38项的int数组的最后一个元素,然后顺次生成余下的37个项。
初始分别生成两个不同的int值(虽不同,但是确定的),相当于指向数组,作为接下来产生随机数用。

然后我们看关键部分:InternalSample方法

private int InternalSample()
{
    int inext = this.inext;
    int inextp = this.inextp;
    if (++inext >= 0x38)
    {
        inext = 1;
    }
    if (++inextp >= 0x38)
    {
        inextp = 1;
    }
    int num = this.SeedArray[inext] - this.SeedArray[inextp];
    if (num < 0)
    {
        num += 0x7fffffff;
    }
    this.SeedArray[inext] = num;
    this.inext = inext;
    this.inextp = inextp;
    return num;
}

这里,当调用Next方法时,总之会运行到这个方法中,这也是整个Random的核心,但是可以看出来,它也是简单的四则运算。


在整个Random中,除了种子,没有任何一个方法过程采用了非线性部件(普通的加减乘除四则运算都是线性运算,像诸如三角函数等是非线性运算),因此就不可能产生非线性随机数。整个随机数序列看似随机,但是却是线性的。

如果我们以默认构造函数构造对象,那么他所使用的TickCount毫无疑问也是线性的,且是严格按顺序递增的值。假如我们以1毫秒为间隔产生若干个Random,并且只调用一次Next,观察他们的值,你会发现他们的值甚至也是按+1排列顺次递增的。
这说明一个什么问题?如果以时间差为基础创建若干Random,然后使用一次Next随即销毁,则这个伪随机数倒更像是一个递增序列了。
所以靠时间差产生若干随机对象并产生随机数的方法仍然是不可行的。只能在需要使用随机数的最大范围内初始化对象,并在整个生命周期内仅使用该对象,不要随意或者按时间相关来创建销毁他。

还需要说明的问题是:按1毫秒为间隔产生随机对象这种做法只是一个理想情况而已,通常我们也模拟不出来,因为.net CLR运行时全权掌控了我们所使用对象的创建、销毁等工作,我们无法再.net中控制CLR在哪一个精确的时刻创建Random对象,因此会出现一个现象,有可能在看似方法的不同位置中创建的Random的代码,到了实际运行时却发现两个Random所产生的随机序列是一样的。这时因为运行时在同一时刻创建了他们,TickCount值没有发生变化。

所以再次说明,尽可能在最大范围内创建和使用Random,且Environment.TickCount是以毫秒计量的单位,而DataTime.Ticks则是以100毫微秒为计量单位,比TickCount细化了10000倍,Environment.TickCount是以操作系统启动开始到当前所经过的毫秒数,而Ticks则是从0001 年 1 月 1 日午夜 12:00:00 以来已经过的时间的以 100 毫微秒为间隔的间隔数,根据计算机产生中断信号的频率和Ticks的数据类型(long,64位有符号整数)来说,可以认为Ticks这个值永远不会重复。

铲铲是也
2008-10-24 00:16
toomee
Rank: 1
等 级:新手上路
帖 子:15
专家分:0
注 册:2008-10-7
收藏
得分:0 
好贴
2008-10-24 09:50
小仙
Rank: 7Rank: 7Rank: 7
来 自:光之谷
等 级:贵宾
威 望:39
帖 子:1812
专家分:1
注 册:2008-8-8
收藏
得分:0 
回复 16# 铲铲 的帖子
呃。。这么长,有点喧宾夺主的味道哈。。不过写的确实是好,我慢慢研究下~


仁者乐膳,智者乐睡。我都爱~
2008-10-24 11:54
铲铲
Rank: 7Rank: 7Rank: 7
等 级:贵宾
威 望:34
帖 子:506
专家分:0
注 册:2006-5-2
收藏
得分:0 
呵呵,正因为你对随机数的探讨,我才开始查阅相关资料,用Reflector察看Random的内部代码。我很久以前也记错了,我印象中Random是调用Win系统随机数发生器而返回随机数,昨天我翻阅以后才发现,原来他仅仅就是一个完全在.net运行时下运行的周期很大的函数,而且我们甚至可以根据种子就推算出第一个随机数是多少,因为整个Random中唯一不确定量就是那个种子。这个非常有趣。

铲铲是也
2008-10-24 12:16
bygg
Rank: 16Rank: 16Rank: 16Rank: 16
来 自:乖乖的心中
等 级:版主
威 望:241
帖 子:13555
专家分:3076
注 册:2006-10-23
收藏
得分:0 
多谢多放,算是学到了

飘过~~
2008-10-24 12:35
快速回复:窗体间传值及随机数生成器小记
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.033263 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved