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

本文关键字:堆栈 栈溢出 异常 随机数 | 更新日期: 2023-09-27 18:25:10

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 中发生了类型为"System.StackOverflowException"的未处理异常.dll {无法计算表达式,因为当前线程处于堆栈溢出状态。

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

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

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

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

即使你解决了这个问题——每次根据当前时间创建一个新的 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;
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;
    }

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

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