随机数发生器 - 可变长度

swa*_*987 2 c# random math integer numbers

目前我的程序(见下文)生成长度为8-12个字符的随机字符串(由数字组成).

public static string GenerateNewCode(int CodeLength)
{
    string newCode = String.Empty;
    int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
    Random random = new Random(seed);

    // keep going until we find a unique code       `
    do
    {
        newCode = random.Next(Convert.ToInt32(Math.Pow(10, CodeLength - 1)), Convert.ToInt32(Math.Pow(10, CodeLength) - 1)).ToString("0000");
    }
    while (!ConsumerCode.isUnique(newCode));

    // return
    return newCode;
}
Run Code Online (Sandbox Code Playgroud)

然而,它们是该方法的问题,当其codeLength为10或更大时,它会导致错误,因为10 9大于int32.MaxValue.

不知道如何解决这个问题.

Eri*_*ert 17

而不是生成从0到10 n -1的数字然后将其转换为字符串,生成从0到9的n个数字,将每个数字转换为字符串,并将它们连接在一起.

我注意到这种技术产生的范围内的数字(比如n = 4)0到9999; 您的原始版本产生的数字从1000到9999.如果您想要保留该属性,则可以生成从1到9而不是0到9的第一个数字.

当然,我这样做的方式更随机,然后'n'连接0 - 9值.

请解释你为什么这么认为.我很着迷于了解为什么人们会相信谎言.

你能不能创建一个Guid.NewGuid().Tostring()并截断最重要的字符来获得一个长度为N的随机字符串?

可以,但你不应该.GUID不保证是随机的,并且GUID的任何比特子集都不保证是唯一的.从GUID中取出位并期望这些位具有GUID的属性就像将舵从飞机上取下并期望方向舵飞行一样.从来没有这样做过.

相反,请将工具用于其设计目的.GUID旨在提供全局唯一标识符,因此无需使用它们.

你没有问的问题,但可能应该:

我的代码还有什么错误或可疑之处?

int seed = unchecked(DateTime.Now.Ticks.GetHashCode()); 
Run Code Online (Sandbox Code Playgroud)

那个代码到底在做什么?首先,随机类已经将当前时间用作种子; 这是不必要的.第二,究竟什么是"未经检查的算术"表达式,其中不包含算术?第三,为什么你会得到哈希码?你没有平衡哈希表!

Random random = new Random(seed);  
Run Code Online (Sandbox Code Playgroud)

如果在同一个tick中调用此方法两次,那么种子将是相同的,因此随机数的序列将是相同的,这意味着您可能会等待很长时间,因为每个生成的数字都将是您的碰撞'独特'集.

一种更好的技术是制作一个随机的静态实例,一次播种.如果您的程序是单线程的,那就没问题了.如果它是多线程的,请确保您不从多个线程访问Random; 它不是线程安全的,它的线程安全违规失败模式不好.

   newCode = random.Next(Convert.ToInt32(Math.Pow(10, CodeLength - 1)),                         Convert.ToInt32(Math.Pow(10, CodeLength) - 
Run Code Online (Sandbox Code Playgroud)

是否真的有必要每次循环计算两次功率,每次都完全相同?在循环开始之前解决一次.代码将更短,更清晰,更快捷.

while (!ConsumerCode.isUnique(newCode));    
Run Code Online (Sandbox Code Playgroud)

如果集合已满,则会永久循环.如果集合几乎已满,那么这会循环长时间.这是一种用于在范围内生成唯一随机数的潜在不良技术.只有在事先知道可能生成的数字远远大于集合的最大大小时才这样做.

那么你的方法对于这个功能会是什么样子?

我倾向于做这样的事情.首先,我想要无限的数字:

// Yield an infinite sequence of pseudo-random digits 0-9
// This method is not thread-safe.
private static Random random = new Random();
static IEnumerable<int> Digits()
{
    while(true)
        yield return random.Next(0, 10);
}
Run Code Online (Sandbox Code Playgroud)

现在我可以生成一个唯一的数字字符串:

// Generates a random code of given length. If it is not
// in the set, adds it and returns the code. If it is
// already in the set, tries again. 
static string AddUniqueCode(int length, HashSet<string> set)
{
    while(true)
    {
        string code = string.Join(null, Digits().Take(length));
        if (set.Add(code))
            return code;
    }
}    
Run Code Online (Sandbox Code Playgroud)

我喜欢我的方法.

如果不可预测性对您很重要,您还可以使Digits方法使用加密强度随机性而不是伪随机性.伪随机数很容易预测.