随机数生成器中的堆栈溢出

时间:2012-01-31 16:14:46

标签: c# random stack-overflow

出于某种原因,当我不在Random类中使用种子时,此代码可以正常工作,但如果我尝试使用DateTime.Now来获取更随机的数字,我会收到StackOverflowException!我的课非常简单。有人能告诉我我在这里做错了什么吗?请参见MakeUniqueFileName。

public class TempUtil
{
    private int strcmp(string s1, string s2)
    {
        try
        {
            for (int i = 0; i < s1.Length; i++)
                if (s1[i] != s2[i]) return 0;
            return 1;
        }
        catch (IndexOutOfRangeException)
        {
            return 0;
        }
    }
    private int Uniqueness(object randomObj)
    {
        switch (randomObj.ToString())
        {
            case "System.Object":
            case "System.String":
                return randomObj.ToString()[0];
            case "System.Int32":
                return int.Parse(randomObj.ToString());
            case "System.Boolean":
                return strcmp(randomObj.ToString(), "True");
            default:
                return Uniqueness(randomObj.ToString());
        }
    }
    public string MakeUniqueFileName()
    {
        return "C:\\windows\\temp\\" + new Random(Uniqueness(DateTime.Now)).NextDouble() + ".tmp";
    }
}

5 个答案:

答案 0 :(得分:11)

你正在调用DateTime.Now.ToString(),它没有给你一个你正在检查的字符串...所以你正在递归,用相同的字符串调用它... 仍然不是您正在寻找的字符串之一。

您无需使用Random来演示此问题。这样做非常容易:

Uniqueness(""); // Tick, tick, tick... stack overflow

期待它做了什么?完全不清楚你的代码意味着在做什么,但我建议你完全放弃Uniqueness方法。事实上,我建议你摆脱整个课程,而是使用Path.GetTempFileName代替。

答案 1 :(得分:2)

简而言之:

应该说

    switch (randomObj.GetType().ToString())

而不是

    switch (randomObj.ToString())

但即便如此,这也不是很聪明。

答案 2 :(得分:1)

您正在将DateTime个实例传递给Uniqueness方法。

这会在ToStringDateTime实例上落实并调用自身,这将是格式化的DateTime字符串(例如"21/01/2011 13:13:01")。

由于此字符串与您的任何切换案例(再次)都不匹配,因此该方法再次调用自身,但在字符串上调用ToString的结果是相同的字符串。

您导致无限调用堆栈导致StackOverflowException

无需拨打Uniquness - 在创建Random实例时,无论如何都会基于当前时间。

我建议您从C#深度网站阅读Random numbers

答案 3 :(得分:1)

Random的无参数构造函数已将当前时间用作种子值。它使用时间刻度,内部用于表示DateTime

然而,这种方法的一个问题是时钟与CPU时钟频率相比非常慢。如果每次需要随机值时都创建Random的新实例,则可能是时钟没有在两次调用之间打勾,从而生成相同的随机数两次。

您可以通过创建Random

的单个实例来解决此问题
public class TempUtil { 
    private static readonly Random random = new Random();

    public string MakeUniqueFileName()
    {
        return @"C:\windows\temp\" + random.NextDouble() + ".tmp";     
    } 
}

这将生成非常好的随机数。


顺便说一下

System.IO.Path.GetTempFileName()

自动创建一个具有唯一名称的空临时文件,并返回该文件的完整路径。

答案 4 :(得分:1)

从哪里开始。 1.已有字符串比较。用它。它已经过调试。 你的独特功能是不合逻辑的。前两个案例项返回一个'S',可能会转换为int。你忽略了第一个案子的休息时间。

你的第三个案例是这样的: if(x ==“System.Int32”)返回int.Parse(“System.Int32”); 这可能会返回32,或解析错误。

你的第四个案例是这样的: if(x ==“System.Boolean”)返回strcmp(“System.Boolean”,“True”); 您的默认情况称为recursevly(sp),导致堆栈溢出(请参阅上面的注释)

为了修复这个程序,我建议你至少阅读一本关于C#的好书,然后重新考虑你的程序,然后编写它。也许Javascript会更合适。