C# 代码仅在逐步执行时给出预期结果?

Posted

技术标签:

【中文标题】C# 代码仅在逐步执行时给出预期结果?【英文标题】:C# code only gives expected results on step through? 【发布时间】:2010-12-02 07:56:42 【问题描述】:

好的,所以我有一个掷骰子应用程序...

当我单步执行代码时,它正常运行并且“结果”包含正确数量的抛出结果,并且它们似乎是随机的,当我让代码运行并执行完全相同的事情时,它会产生一组相同的数字.

我确定这是一个我看不到的逻辑错误,但摆弄了几个小时并没有改善这种情况,因此非常感谢任何帮助。 :)

    class Dice


    public int[] Roll(int _throws, int _sides, int _count)
    
        Random rnd = new Random();
        int[] results = new int[_throws];
        // for each set of dice to throw pass data to calculate method
        for (int i = 0; i < _throws; i++)
        
            int thisThrow = Calculate(_sides, _count);
            //add each throw to a new index of array... repeat for every throw
            results[i] = thisThrow; 
        

        return results;
    


    private int Calculate(int _sides, int _count)
    
        Random rnd = new Random();
        int[] result = new int[_count];
        int total = 0;
        //for each dice to throw put data into result
        for (int i = 0; i < _count; i++)
        
            result[i] = rnd.Next(1, _sides);
        
        //count the values in result
        for (int x = 0; x < _count; x++)
        
            total = total + result[x];
        
        //return total of all dice to Roll method
        return total;
    

【问题讨论】:

【参考方案1】:

第一个错误:永远不要使用多个 Random 实例,使用单个实例,然后将其与其他参数一起传递。

【讨论】:

@Ian:我已经看到这种情况发生太多次了,没有立即发现 :) @leppie:是的。看看有多少涉及 RNG 的 SO 问题基本上是这个问题的变体会很有趣......【参考方案2】:

当您创建“随机 rnd = new Random();”时它是按当前时间播种的。当你调试你的代码时(这需要时间),它每次都会以不同的方式播种。

创建 1 个 Random 实例,并在任何地方引用它。

【讨论】:

【参考方案3】:

每次您需要创建一个数字时,您都会创建一个随机类。这样做会给你带来疯狂的结果。

请看这里:FROM MSDN

这个问题可以通过创建单个 Random 对象而不是多个对象来避免。

为了提高性能,请创建一个 Random 对象以随着时间的推移生成许多随机数,而不是重复创建一个新的 Random 对象以生成一个随机数。

例如创建一个 Random 的私有实例...

【讨论】:

【参考方案4】:

除了前面提到的……

将随机用于骰子、纸牌游戏、选择随机图像等。如果出于安全原因需要创建随机数,请使用 System.Security.Cryptography.RandomNumberGenerator。这个简单的例子展示了如何创建一个随机整数。

        RandomNumberGenerator gen = RandomNumberGenerator.Create();
        byte[] myBytes = new byte[4];
        gen.GetBytes(myBytes);
        int myValue = (BitConverter.ToInt32(myBytes, 0));

除非您有安全需要,否则请勿使用此功能。性能低于 Random 类。我想你可以用它来播种 Random 但这可能是矫枉过正。

编辑:我突然想到我从未测试过这个。快速性能测试显示如下:

1,000,000 个随机数: 随机数生成器:2.6 秒 随机:0.015 秒。

所以 Random 大约快 150 倍。

【讨论】:

两件事。首先,使用随机数作为伪随机数生成器的种子实际上并没有给你带来更多的随机性;伪 RNG 的输出仍然是可预测的。 其次,加密强度 RNG 的性能不仅取决于它必须做的数学运算,还取决于机器为RNG 进行操作。你知道,RNG 不会无中生有地发明熵!熵必须来自某个地方,而熵就像带宽、内存或处理器时间一样有限。你每秒只能得到这么多的熵;尝试使用大量熵当然会阻塞,直到有更多熵可用,就像尝试使用处理器或网络带宽阻塞一样。【参考方案5】:

给构造函数 Random 一个种子。这就是问题所在。

http://msdn.microsoft.com/en-us/library/aa329890%28VS.71%29.aspx

Random r = new Random(DateTime.Now.Millisecond);

【讨论】:

使用毫秒作为种子比默认的 Ticks 还要糟糕。在大多数情况下,滴答种子很好,就像其他人所说的那样,不要重新创建 Random 类,因此将其重新播种回相同的值。 啊。我已经习惯了 C 风格的 rand 函数。

以上是关于C# 代码仅在逐步执行时给出预期结果?的主要内容,如果未能解决你的问题,请参考以下文章

代码在数独中没有给出预期的结果

从线程抛出异常并没有给出预期的结果

UIColor.Clear 在swift3的部分标题中使用时没有给出预期的结果

多处理池的python保存数据在linux上没有给出预期的结果

如果结果已经可用,则仅在单击按钮时启动异步任务并执行操作,否则等待结果然后执行操作

除法没有给出预期的结果