Random 种子问题

 

1:随机数生成器

Random 是 .NET 的伪随机数生成器,要生成各种类型的随机数,必须先得到它的实例对象,然后再生成随机数

2:种子

随机数的生成是从种子值开始。 如果反复使用同一个种子,就会生成相同的数字系列,产生不同序列的一种方法是使种子值与时间相关

3:对象实例

默认情况下,Random 类的无参数构造函数使用系统时钟生成其种子值

参数化构造函数可提供一个 Int32 类型的数字为起始值

4:生成方案

方案1:只实例化一个对象,多次方法调用

Random rnd = new Random();
int i1 = rnd.Next(10);
int i2 = rnd.Next(10);
 
// 简单,方便,常用,生成的数字分布均匀,每个数字返回的可能性均相等。
// 一般是实例为静态对象,以减少实例化的次数,避免产生相同的种子值,如下:
private static RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();

方案2:每次方法调用都用一个新的实例(无参)

Random rnd1 = new Random();
int i1 = rnd2.Next(10);
 
Random rnd2 = new Random();
int i2 = rnd2.Next(10);
 
// 两个随机数十有八九相同
// 默认种子值是从系统时钟派生而来的,具有有限的分辨率。
// 因此,通过调用默认构造函数而频繁创建的不同对象将具有相同的默认种子值,因而会产生几组相同的随机数。

解决方案:

阻塞当前线程一小段时间

Random rnd1 = new Random();
System.Threading.Thread.Sleep(500);
Random rnd2 = new Random();

或者:应用一个算法来区分每个调用的种子值。

例如,下面的代码使用右移位运算符为多个可以使用相同时间值初始化的 Random 对象(在 1 和大约 28 个对象之间)生成不同的种子值。

int count = 4;
Random[] rnds = new Random[count];
 
for (int i = 0; i < count; i++)
{
    rnds[i] = new Random(unchecked((int)(DateTime.Now.Ticks >> i)));
}

5:通用数字和字母随机生成方案

数组方式:略

字符串方式:不灵活,但比较简便,用于验证码已足够

string str = @"0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ";
 
public string GetMix(Random rnd)
{
    // 返回数字
    // return rnd.Next(10).ToString();
 
    // 返回小写字母
    // return str.Substring(10+rnd.Next(26),1);
 
    // 返回大写字母
    // return str.Substring(36+rnd.Next(26),1);
 
    // 返回大小写字母混合
    // return str.Substring(10+rnd.Next(52),1);
 
    // 返回小写字母和数字混合
    // return str.Substring(0 + rnd.Next(36), 1);
 
    // 返回大写字母和数字混合
    // return str.Substring(0 + rnd.Next(36), 1).ToUpper();
 
    // 返回大小写字母和数字混合
    return str.Substring(0 + rnd.Next(61), 1);
}

6:用随机数填充指定字节的数组

Random rnd = new Random();
 
// 数组长度自定义 
byte[] bs = new byte[9999];
 
// 字节数组的每个元素均设置为一个大于等于零而小于或等于 MaxValue 的随机数。MaxValue=255,可取上界值 
rnd.NextBytes(bs);

7:生成大于等于 0.0 小于 1.0 的双精度浮点数

Random rnd = new Random();
 
// 大于等于 0.0 并且小于 1.0 的双精度浮点数。 
double d = rnd.NextDouble();
 
// 格式化为 5 位小数,当然还有更多种格式化 
string s = string.Format("{0:F5}", d);

8:生成随机整数

Random rnd = new Random();
 
// 大于等于零且小于 MaxValue 的 32 位带符号整数。MaxValue=2,147,483,647,不可取上界值 
int i1 = rnd.Next();
 
// 大于等于零且小于 maxValue 的 32 位带符号整数,不可取上界值 
int i2 = rnd.Next(10);
 
// 一个大于等于 minValue 且小于 maxValue 的 32 位带符号整数,不可取上界值,可以取负值 
int i3 = rnd.Next(-10, 100);

9:生成随机大写字母

public string GetUpperCase(Random rnd)
{
    // A-Z  ASCII值  65-90 
    int i = rnd.Next(65, 91);
    char c = (char)i;
    return c.ToString();
}

10:生成随机小写字母

public string GetLowerCase(Random rnd)
{
    // a-z  ASCII值  97-122 
    int i = rnd.Next(97, 123);
    char c = (char)i;
    return c.ToString();
}

11:生成随机大小写字母混合

public string GetLetter(Random rnd)
{
    // A-Z  ASCII值  65-90
    // a-z  ASCII值  97-122
    int i = rnd.Next(65, 123);
    char c = (char)i;
    if (char.IsLetter(c))
    {
        return c.ToString();
    }
    else
    {
        // 递归调用,直到随机到字母
        return GetLetter(rnd);
    }
}

12:生成随机大小写字母和数字混合

public string GetChar(Random rnd)
{
    // 0-9
    // A-Z  ASCII值  65-90
    // a-z  ASCII值  97-122
    int i = rnd.Next(0, 123);
    if (i < 10)
    {
        // 返回数字
        return i.ToString();
    }
 
    char c = (char)i;
 
    // 返回小写字母加数字
    // return char.IsLower(c) ? c.ToString() : GetChar(rnd);
 
    // 返回大写字母加数字
    // return char.IsUpper(c) ? c.ToString() : GetChar(rnd);
 
    // 返回大小写字母加数字
    return char.IsLower(c) ? c.ToString() : GetChar(rnd);

}

shenqiboy
posted on 2012-12-05 10:34  Alan Yang  阅读(345)  评论(0编辑  收藏  举报