当前位置:编程学习 > C#/ASP.NET >>

C# 产生随机数

  private void Form1_Load(object sender, EventArgs e)
        {    
            double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
            for (int i = 0; i < 50; i++)
            {
                Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));
                while (s > 1 || s == 0)
                {
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";

            }
        }

winform窗体,textbox显示计算出的正态分布随机数。
现在问题是,运行之后产生的数据都是一样的。但是调试单步执行,数据又不同,大家有没有什么解决的办法吗? C# random --------------------编程问答-------------------- new Random要放在循环外面 --------------------编程问答-------------------- 把  Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));
放到循环外边 --------------------编程问答-------------------- 放在循环外面,数据也是重复的 --------------------编程问答-------------------- 我刚才在VS上把你的代码运行了一下.  
问题就是 那个while 循环 只能进去2次  所以 只有2个数字 剩下的都是循环他们的.

不知道你那么多数字是干啥的,反正你解决这个问题貌似就行了... --------------------编程问答--------------------
 static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }

        Random rand1 = new Random(GetRandomSeed()); 

        private void Form1_Load(object sender, EventArgs e)
        {

           // Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));
            double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
            for (int i = 0; i < 50; i++)
            {
                
                while (s > 1 || s == 0)
                {
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";

            }
        }

上面的方法试了,数据还是重复的 --------------------编程问答-------------------- 如果new Random()时没传递不一样的种子的话,生成的随机数,在顺序上是一样的,建议,可以生成一个静态的Random这样的 --------------------编程问答-------------------- 贡献下我自己的高斯分布的类吧..

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
///正态分布帮助
/// </summary>
public class NormalDistribution
{
    public NormalDistribution()
    {
        //
        //TODO: 在此处添加构造函数逻辑
        //
    }
    /// <summary>
    /// 正态分布随机数
    /// </summary>
    const int N = 100;
    const int MAX = 50;
    const double MIN = 0.1;
    const int MIU = 40;
    const int SIGMA = 1;
    static Random aa = new Random((int)(DateTime.Now.Ticks / 10000));
    /// <summary>
    /// 产生(min,max)之间均匀分布的随机数
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public double AverageRandom(double min, double max)
    {
        int MINnteger = (int)(min * 10000);
        int MAXnteger = (int)(max * 10000);
        int resultInteger = aa.Next(MINnteger, MAXnteger);
        return resultInteger / 10000.0;
    }
    /// <summary>
    /// 正态分布概率密度函数
    /// </summary>
    /// <param name="x"></param>
    /// <param name="miu"></param>
    /// <param name="sigma"></param>
    /// <returns></returns>
    public double Normal(double x, double miu, double sigma)
    {
        return 1.0 / (x * Math.Sqrt(2 * Math.PI) * sigma) * Math.Exp(-1 * (Math.Log(x) - miu) * (Math.Log(x) - miu) / (2 * sigma * sigma));
    }
    /// <summary>
    /// 产生正态分布随机数
    /// </summary>
    /// <param name="miu"></param>
    /// <param name="sigma"></param>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public double Random_Normal(double miu, double sigma, double min, double max)
    {
        double x;
        double dScope;
        double y;
        do
        {
            x = AverageRandom(min, max);
            y = Normal(x, miu, sigma);
            dScope = AverageRandom(0, Normal(miu, miu, sigma));
        } while (dScope > y);
        return x;
    }
    /// <summary>
    /// 指数分布随机数
    /// </summary>
    /// <param name="const_a">const_a是指数分布的参数λ</param>
    /// <returns></returns>
    public double RandExp(double const_a)
    {
        Random rand = new Random(Guid.NewGuid().GetHashCode());
        double p;
        double temp;
        if (const_a != 0)
            temp = 1 / const_a;
        else
            throw new System.InvalidOperationException("除数不能为零!不能产生参数为零的指数分布!");
        double randres;
        while (true) //用于产生随机的密度,保证比参数λ小
        {
            p = rand.NextDouble();
            if (p < const_a)
                break;
        }
        randres = -temp * Math.Log(temp * p, Math.E);
        return randres;
    }

    /// <summary>
    /// 求出数据平均值,并保留三位小数
    /// </summary>
    /// <param name="Valist">数据集合</param>
    /// <returns></returns>
    public double average(List<double> Valist)
    {
        double sum = 0;
        foreach (double d in Valist)
        {
            sum = sum + d;
        }
        double revl = System.Math.Round(sum / Valist.Count, 2);
        return revl;
    }
    /// <summary>
    /// 求数据集合标准差
    /// </summary>
    /// <param name="ValList"></param>
    /// <returns></returns>
    public double stdev(List<double> ValList)
    {
        double avg = average(ValList);
        double sumstdev = 0;
        foreach (double d in ValList)
        {
            sumstdev = sumstdev + (d - avg) * (d - avg);
        }
        double stdeval = System.Math.Sqrt(sumstdev);
        return System.Math.Round(stdeval, 2);
    }
}

--------------------编程问答-------------------- O(∩_∩)O~ 下班了,回去再试试大家提供的方法,先谢谢你们啦 --------------------编程问答--------------------  private void Form1_Load(object sender, EventArgs e)
        {    
            double u1, u2, v1 = 0, v2 = 0, z1 = 0, z2 = 0;
            for (int i = 0; i < 3; i++)
            {
               
                double s = 0;
                while (s > 1 || s == 0)
                {
                    Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";
 
            }
        }
其实这只是小小的改动,电脑没你想象的那么快的可以那么快就可以产生那么多的随机数,它也需要时间的,估计是反应不过来就把上次的内容输出了,你可以加个timer控件看看,一次次它有时间产生随机数当然是可以成功的! --------------------编程问答-------------------- 上面很多是误人子弟呀

 static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        } 

        private void Form1_Load(object sender, EventArgs e)
        {

           // Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));
            double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
            for (int i = 0; i < 50; i++)
            {
                Random rand1 = new Random(GetRandomSeed());
                Random rand2 = new Random(GetRandomSeed());
                while (s > 1 || s == 0)
                {
                    u1 = rand1.NextDouble();
                    u2 = rand2.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";

            }
        }
C#的Random类默认是用当前的时间做为Seed的,所以如果时间一样的话,你怎么调用都是一样的,所以要保证真正的随机,必须保证获取随机数的时候,随机种子是不一样的。 --------------------编程问答--------------------  Random rd = new Random();
 rd.Next(0, str.Length);
 你给next一下 试试。 --------------------编程问答--------------------
http://blog.csdn.net/conmajia/article/details/7596149 --------------------编程问答-------------------- 上面的方法都试过了,不管怎么改,数据都还是重复的,除非调试单步执行会生成不一样的数据。
#7的代码可以用 --------------------编程问答-------------------- 有什么办法可以延缓代码执行吗 --------------------编程问答--------------------
引用 14 楼 handhappy 的回复:
有什么办法可以延缓代码执行吗
thread。sleep(100); --------------------编程问答-------------------- 楼主,你自己先写一简单的测试随机函数三,并且我估计是你的逻辑有问题,写程序一定要学会调试 --------------------编程问答-------------------- 问题解决了,用Thread.Sleep()延长时间,这样每次获取的种子数据就不一样了,谢谢大家的解答。 --------------------编程问答-------------------- 代码贴出来大家看下
static int GetRandomSeed()
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            double u1, u2, v1 = 0, v2 = 0, z1 = 0, z2 = 0;
            for (int i = 0; i < 50; i++)
            {
                double s = 0;
                //为了保证lns<0,要求s<1且s !=0,若不满足条件,则重新产生u和v
                Thread.Sleep(100);
                Random rand1 = new Random(GetRandomSeed());

                while (s > 1 || s == 0)
                {
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "\r\n";

            }
        }
    }
--------------------编程问答-------------------- 这个实验证明了.net的Random是将当前时间带入运算的。当种子正好是当前时间时,会产生相同结果。 --------------------编程问答-------------------- 因为程序计算比较快,50次循环下来,DateTime.Now.Ticks值根本变

for (int i = 0; i < 50; i++)
{
    this.txtContent.Text += DateTime.Now.Ticks.ToString()+"<br/>";
}

得到的结果全部是:635085529614859793
Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));并不是随机的 而是根据种子数值通过算法计算出来的 --------------------编程问答-------------------- LZ  
这个是别人给的资源  里面有用到随机数  LZ可以看看
http://pan.baidu.com/share/link?shareid=1455601487&uk=1677815159 --------------------编程问答--------------------
引用 14 楼 handhappy 的回复:
有什么办法可以延缓代码执行吗

用timer也可以延长! --------------------编程问答-------------------- 其实不需要延时,把random放到外面,再把while改成dowhile就行了。 --------------------编程问答--------------------

private void Form1_Load(object sender, EventArgs e)
        {
           double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
           Random rand1 = new Random();
            for (int i = 0; i < 50; i++)
            {
                do
                {
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                while (s > 1 || s == 0);
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";
 
            }
        }
--------------------编程问答-------------------- 怎么不想下  , 当 s 在(0,1]之间的时候是不会进while循环的  所以 你能不能保证s一定不在那个区间里面? --------------------编程问答--------------------
引用 24 楼 u011303459 的回复:

private void Form1_Load(object sender, EventArgs e)
        {
           double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
           Random rand1 = new Random();
            for (int i = 0; i < 50; i++)
            {
                do
                {
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                while (s > 1 || s == 0);
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";
 
            }
        }

试了下,确实可以,为什么把while改成do-while结果会不一样呢? --------------------编程问答-------------------- 因为使用while (s > 1 || s == 0),判断的变量是s。
但是在for (int i = 0; i < 50; i++)循环里面你没有对s重新赋值,这样i=1-49使用的都是i=0时的s,换句话说你的while (s > 1 || s == 0)循环只能i=0的时候才会进入。 --------------------编程问答-------------------- while是先判断,后执行。do-while是先执行,后判断。
--------------------编程问答-------------------- 这么简单的问题回答的人好多阿 --------------------编程问答--------------------
引用 楼主 handhappy 的回复:
  private void Form1_Load(object sender, EventArgs e)
        {    
            double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
            for (int i = 0; i < 50; i++)
            {
                Random rand1 = new Random(unchecked((int)DateTime.Now.Ticks));
                while (s > 1 || s == 0)
                {
                    u1 = rand1.NextDouble();
                    u2 = rand1.NextDouble();
                    v1 = 2 * u1 - 1;
                    v2 = 2 * u2 - 1;
                    s = v1 * v1 + v2 * v2;
                }
                z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
                z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                textBox1.Text += z1.ToString() + "     " + z2.ToString() + "    ";

            }
        }

winform窗体,textbox显示计算出的正态分布随机数。
现在问题是,运行之后产生的数据都是一样的。但是调试单步执行,数据又不同,大家有没有什么解决的办法吗?


和随机数一毛钱关系都没有 while语句只执行了一次

    string ss="";
        double u1, u2, v1 = 0, v2 = 0, s = 0, z1 = 0, z2 = 0;
        Random rand1;
        for (int i = 0; i < 50; i++)
        {
            rand1 = new Random(unchecked((int)DateTime.Now.Ticks)+i);          
            //while (s > 1 || s == 0)
            //{
                u1 = rand1.NextDouble();
                u2 = rand1.NextDouble();
                v1 = 2 * u1 - 1;
                v2 = 2 * u2 - 1;
                s = v1 * v1 + v2 * v2;
                
            //}
            //z1 = Math.Sqrt(-2 * Math.Log(s) / s) * v1;
            //z2 = Math.Sqrt(-2 * Math.Log(s) / s) * v2;
                ss += u1.ToString() + "     " + u2.ToString() + "<br />";

        }
        Response.Write(ss);
--------------------编程问答-------------------- 我表示难的问题找谁呢 --------------------编程问答--------------------
引用 31 楼 jiaoshiyao 的回复:
我表示难的问题找谁呢

只有靠 本拉登了 --------------------编程问答-------------------- public string returnStr()

        {

            Random rd = new Random();

            string str = "";

            string[] s = { "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" };

            for (int i = 0; i < 20; i++)

            {

                

                str += s[rd.Next(26)].ToString()+".";

            }

            return str.ToString();

        }
--------------------编程问答--------------------
引用 32 楼 zxy397472251 的回复:
Quote: 引用 31 楼 jiaoshiyao 的回复:

我表示难的问题找谁呢

只有靠 本拉登了
--------------------编程问答-------------------- 学习了,这个很有用!
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,