|
|
Posted on 2005-01-25 11:40 柚子Nan 阅读(2258) 评论(14) 编辑 收藏 网摘 所属分类: [技术.Net]
今天上午同事遇到一个问题,他要生成一个任意位数的随机数字和大写字母的组合,一个很简单的问题。同事的代码如下:
private string GetRandomString(int nDigit)
{
//将数字和大写字母组成一个字符串
string[] arySource={"0","1","2","3","4","5","6","7","8","9"
,"A","B","C","D","E","F","G","H","I","J","K","L"
,"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
string strResult = "";
string strTemp = "";
for (int i = 0; i < nDigit; i++)
{
strTemp = arySource[new Random().Next(36)];
strResult += strTemp;
}
return strResult;
}
然后在另外一个按钮的事件里
private void Button1_Click(object sender, System.EventArgs e)
{
TextBox1.Text = GetRandomString (4);
}
如果运行程序,总是得到4位相同的数字或者字母。
但是,如果在for循环内部设置了断点,然后F9单步跟踪,就产生了4位不同的数字或者字母。
就是这样一个结论:
如果F5运行程序就得到4位相同的串
如果单步调试F9 就得到随机的串
试试看?
Feedback
在极短的时间内
new Random().Next(36)
会返回相同的值.
建议
Random r=new Random(Guid.NewGuid().GetHashCode());
for(...)
{
.... r.Next(36);
}
楼上说得果然牛!
后来,我找到了一个解决方法 是这个对象new Random() 出了问题 如果把上述代码修改为 privatestring GetRandomString(int nDigit) { //将数字和大写字母组成一个字符串 string[] arySource={"0","1","2","3","4","5","6","7","8","9" ,"A","B","C","D","E","F","G","H","I","J","K","L" ,"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}; string strResult = ""; string strTemp = ""; Random aRandom = new Random(); for (int i = 0; i < nDigit; i++) { strTemp = arySource[aRandom.Next(36)]; strResult += strTemp; } return strResult; } 那么无论是单步调试F9,还是整体运行F5,都将得到正确的随机字符串。 好奇怪的问题,谁能解释解释
谢谢Lostinet
后来在msdn找到了答案:
Random 类,伪随机数是以相同的概率从一组有限的数字中选取的。所选数字并不具有完全的随机性,因为它们是用一种确定的数学算法选择的,但是从实用的角度而言,其随机程度已足够了。
随机数的生成是从种子值开始。如果反复使用同一个种子,就会生成相同的数字系列。产生不同序列的一种方法是使种子值与时间相关,从而对于 Random 的每个新实例,都会产生不同的系列。
要提高性能,请创建一个 Random,以便随着时间的推移可以生成很多随机数,而不要重复新建 Random 来生成一个随机数。
你这样做依然是有问题的.
连续的两次 GetRandomString 会返回同样的字符串.
应该将
Random aRandom = new Random();
改为类的一个静态属性:
private static Random aRandom = new Random();
private Random rnd=new Random();
private string GetRandomString(int nDigit)
{
//将数字和大写字母组成一个字符串
string[] arySource={"0","1","2","3","4","5","6","7","8","9"
,"A","B","C","D","E","F","G","H","I","J","K","L"
,"M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
string strResult = "";
string strTemp = "";
for (int i = 0; i < nDigit; i++)
{
strTemp = arySource[rnd.Next(36)];
strResult += strTemp;
}
return strResult;
}
private void button1_Click(object sender, System.EventArgs e)
{
textBox1.Text = GetRandomString (4);
}
以前用vb的时候不就是这样吗?道理和vb中的差不多,random()函数是与时间有关的。
Lostinet 是的
TextBox1.Text = GetRandomString (4) + GetRandomString (4);
得到的结果是GetRandomString (4)的复制1倍
最终的解决方案就是Lostinet 所说的
1、Random r=new Random(Guid.NewGuid().GetHashCode());
2、梁利锋 所说的设置为static变量。static必然与时间相关累积了
NewGuid() 也是和时间相关的,只不过增加了对于电脑其它部分的一些信息,如网卡号等。而且,NewGuid() 本身想必也是使用Random产生的。
static 是为了保证初始化只被执行一次,其实应该在整个应用程序中共享这个Random实例,才保证了即使在不同的类中,也不会因执行的时间太接近而出现重复。
public class Test
{
private static Random rand = new Random();
private string arySource = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public void Run()
{
string s = GetRandomString(4) + ":" + GetRandomString(4);
Console.WriteLine("{0}", s);
}
private string GetRandomString(int nDigit)
{
string strResult = "";
for (int i=0; i<nDigit; i++)
{
strResult += arySource[rand.Next(36)];
}
return strResult;
}
}
在VB里使用随机也是这样,当时是怎么处理的忘了,呵呵
看来和C的random是一样的道理.
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
main()
{
int i=0;
randomize();
for(i;i<100;i++)
{
/* randomize(); */
printf("%d ",random(10);
}
}
new Random(int)作为一个种子就可以了
|