使用随机数时间歇性堆栈溢出异常

时间:2012-02-19 14:22:35

标签: c# random recursion stack-overflow

public int S1x;

public void Execute()
{
    Random random = new Random();
    S1x = random.Next(14, 146);
    if (S1x % 15 != 0)
        Fix(S1x);
}

public int Fix(int SX)
{                
    Random randomG = new Random();
    SX = randomG.Next(14, 146);
    if (SX % 15 != 0)                               
        Fix(SX); // This is the recursion

    return SX;
}

每次运行它都会正常工作,但之后我会尝试再次编译并运行它会给我这个错误:

  

System.StackOverflowException未处理   mscorlib.dll中发生了未处理的“System.StackOverflowException”类型异常   {无法计算表达式,因为当前线程处于堆栈溢出状态。}

而且,是的,我知道有一种更简单的方法可以做到这一点,但我的方法是将值设置为等于14到146之间的随机数,同时还要确保它是15的倍数,应该仍然有效仍然。

我真的很困惑为什么它有时只给我错误信息。

那有什么问题呢?为什么它被标记为无限递归,即使它没有任何无限的呢?

2 个答案:

答案 0 :(得分:18)

即使你解决了这个问题 - 你每次根据当前时间播种时都在创建一个新的Random对象 - 你的代码既不正确也不高效。请记住,递归方法需要具有以下特征才是正确的:

  • 无需递归即可解决一个小问题
  • 递归步骤使问题变小
  • 有限数量的递归总能将问题简化为一个微不足道的问题

您没有任何这些属性,因此递归是错误的解决方案

如果您想要一个介于14和146之间的随机数以及15的倍数,则不需要任何递归。唯一这样的数字是15,30,45,60,75,90,105,120和135.所以只说:

private int[] array = { 15, 30, 45, 60, 75, 90, 105, 120, 135 };
private Random random = new Random();
...

return array[random.Next(0, array.Length)];

甚至更好:选择1到9之间的随机数,并将其乘以15。

return random.Next(1, 10) * 15;

答案 1 :(得分:4)

new Random()种子本身Environment.TickCount(系统启动后毫秒)生成伪随机数,如果你用rand.Next(x, y);的第一次调用两次使用相同的数字播种它每次都是相同的值。

    public int Fix(int SX)
    {

        Random randomG = new Random();
        SX = randomG.Next(14, 146);
        if (SX % 15 != 0)
        {

            Fix(SX); // This is the recursion
        }           
        return SX;
    }

由于每次运行此函数(在相同的毫秒内)时都在创建Random的新实例,因此它将生成相同的数字。因此,在生成新数字之前,它会被调用数千次。如果你这样做:

    Random randomG = new Random();
    public int Fix(int SX)
    {
        SX = randomG.Next(14, 146);
        if (SX % 15 != 0)
        {
            Fix(SX); // This is the recursion
        }           
        return SX;
    }

每次调用它时,至少它会生成一个新的随机数,这样你就更有可能在堆栈溢出之前找到你想要的那个。

编辑:我忘了提到为什么递归对于实现这一目标是一个坏主意。实际上不使用上面的代码,它仍然是一个糟糕的解决方案。我现在不会修改我的答案,因为答案要好得多has been posted