随机双数的多次迭代往往变小

Hou*_*man 9 .net c# random double

我正在创建一个股票交易模拟器,其中最后几天的交易价格被视为开盘价并在当天模拟.

为此,我生成的随机双数可能是lastTradePrice的-5%,比lastTradePrice高5%.然而,在大约240次迭代之后,我看到生成的双数如何越来越小,接近于零.

Random rand = new Random();
Thread.Sleep(rand.Next(0,10));
Random random = new Random();
double lastTradeMinus5p = model.LastTradePrice - model.LastTradePrice * 0.05;
double lastTradePlus5p = model.LastTradePrice + model.LastTradePrice * 0.05;
model.LastTradePrice = random.NextDouble() * (lastTradePlus5p - lastTradeMinus5p) + lastTradeMinus5p;
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我试图通过利用获得随机种子Thread.sleep().然而它并非真正随机化.为什么总会产生较小的数字呢?

在此输入图像描述

更新:

数学本身实际上很好,尽管Jon已经证明了它的下降趋势.此处还解释在范围之间获取随机双数.

真正的问题是种子Random.我遵循Jon的建议,Random在所有三个价格的线程中保持相同的实例.这已经产生了更好的结果; 价格实际上反弹回来了.我仍在调查并接受如何改进这一建议的建议.Jon给出的链接提供了一篇很好的文章,介绍了如何为每个线程生成一个随机实例.

顺便说一下,如果你有兴趣,整个项目开源的.(在浏览器中使用WCF,WPF,PRISM 4.2,.NET 4.5堆栈)

TransformPrices呼叫是发生在这里的一个单独的线程.

如果我保持相同的随机实例会发生这种情况: 在此输入图像描述

这是通过RandomProvider.GetThreadRandom();文章中指出的: 在此输入图像描述

Jon*_*eet 11

首先,称Thread.Sleep这样是不是得到一个不同的种子的好方法.最好使用Random每个线程的单个实例.有关建议的方法,请参阅我的随机性文章.

但是,您的代码本身也存在偏差.假设我们从随机数生成器"随机"获得0.0和1.0,从100美元的价格开始.这会给:

  • 第0天:100美元
  • 第1天:95美元(-5%= 5美元)
  • 第2天:99.75美元(+ 5%= 4.75美元)

现在我们可以随机获得1.0和0.0:

  • 第0天:100美元
  • 第1天:105美元(+ 5%= 5美元)
  • 第2天:99.75美元(-5%= 5.25美元)

请注意我们在这两种情况下都是如此,尽管这是"公平的".如果值增加,这意味着它可以在骰子的下一卷上进一步下降,可以这么说......但是如果值减小,它就不能反弹到目前为止.

编辑:为了了解"合理公平"的RNG如何仍然可能给出一个递减值,这里有一个小控制台应用程序:

using System;

class Test
{
    static void Main()
    {
        Random random = new Random();
        int under100 = 0;
        for (int i = 0; i < 100; i++)
        {
            double price = 100;
            double sum = 0;

            for (int j = 0; j < 1000; j++)
            {
                double lowerBound = price * 0.95;
                double upperBound = price * 1.05;
                double sample = random.NextDouble();
                sum += sample;
                price = sample * (upperBound - lowerBound) + lowerBound;                
            }
            Console.WriteLine("Average: {0:f2} Price: {1:f2}", sum / 1000, price);
            if (price < 100)
            {
                under100++;
            }
        }
        Console.WriteLine("Samples with a final price < 100: {0}", under100);
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的机器,"平均"值始终非常接近0.5(很少超过0.52小于0.48以上),但大多数的"最终价格"总是低于100 - 其中约65-70%.