0

我正在研究轮盘赌类,它的功能应该或多或少类似于常规轮盘赌轮盘,其中某些数字可以占据轮盘赌轮的较大部分,因此被选中的可能性更高。

到目前为止,它已经通过了更基本的单元测试,也就是说,它以编程方式工作,我可以创建一个轮盘赌并用一堆通用值填充它,它会做到这一点。

然而,当涉及到我的概率测试时,我决定将其作为 6 面骰子进行尝试,经过 10,000,000 次试验后,它应该产生大约 3,5 的平均骰子,不幸的是它甚至没有接近之后的平均值10,000,000 次试验大约是 2,9,所以我猜我的号码选择有一个弱点?我在下面发布了单元测试和实际代码:

public class RouletteNumber<T>
    {
        public readonly T Number;
        public readonly int Size;

        public RouletteNumber(T number, int size)
        {
            this.Number = number;
            this.Size = size;
        }

        public static RouletteNumber<T>[] CreateRange(Tuple<T, int>[] entries) 
        {
            var rouletteNumbers = new RouletteNumber<T>[entries.Length];

            for (int i = 0; i < entries.Length; i++)
            {
                rouletteNumbers[i] = new RouletteNumber<T>(entries[i].Item1, entries[i].Item2);
            }

            return rouletteNumbers;
        }
    }

public class RouletteWheel<T>
    {
        private int size;
        private RouletteNumber<T>[] numbers;
        private Random rng;

        public RouletteWheel(params RouletteNumber<T>[] rouletteNumbers)
        {
            size = rouletteNumbers.Length;
            numbers = rouletteNumbers;
            rng = new Random();

            //Check if the roulette number sizes match the size of the wheel
            if (numbers.Sum(n => n.Size) != size)
            {
                throw new Exception("The roulette number sections are larger or smaller than the size of the wheel!");
            }
        }

        public T Spin()
        {
            // Keep spinning until we've returned a number
            while (true)
            {
                foreach (var entry in numbers)
                {
                    if (entry.Size > rng.Next(size))
                    {
                        return entry.Number;
                    }
                }
            }
        }
    }

[TestMethod]
        public void DiceRouletteWheelTest()
        {
            double expected = 3.50;
            var entries = new Tuple<int, int>[] 
            {
                Tuple.Create(1, 1),
                Tuple.Create(2, 1),
                Tuple.Create(3, 1),
                Tuple.Create(4, 1),
                Tuple.Create(5, 1),
                Tuple.Create(6, 1)
            };
            var rouletteWheel = new RouletteWheel<int>(RouletteNumber<int>.CreateRange(entries));
            var results = new List<int>();

            for (int i = 0; i < 10000000; i++)
            {
                results.Add(rouletteWheel.Spin());
            }

            double actual = results.Average();

            Assert.AreEqual(expected, actual);
        }
    }
4

2 回答 2

3

当您调用Random.Next(n)它时,它会生成一个介于 0 和n-1之间的随机数,而不是介于 0 和 n 之间的随机数。

你有考虑过吗?

事实上,对于一个 6 面骰子,你会想调用Random.Next(1, 7)

于 2014-06-18T09:43:53.290 回答
1

也许我没有正确理解它,但我猜问题出在这里:

while (true)
{
  foreach (var entry in numbers)
  {
    if (entry.Size > rng.Next(size))
    {
      return entry.Number;
    }
  }
}

每次执行 if 检查时,您都在计算 rng.Next。所以第一个数字有六分之一的机会被选中。数字 2(数字中的下一个条目)则有六分之二的机会被选中(新数字呈现在 1 和 6 之间)。但是,由于您总是从头开始,因此您最终将获得更多较低的数字。
我也看不到在普通随机生成器中需要 while(true) 。我猜这可能会起作用,并且看起来像您当前的代码:

var rndValue = rng.Next(size);
foreach (var entry in numbers)
  {
    if (entry.Size > rndValue)
    {
        return entry.Number;
    }
}
于 2014-06-18T10:08:54.010 回答