【问题标题】:How to Generate Same key that is Generated by Previously Random in c#如何在c#中生成先前随机生成的相同密钥
【发布时间】:2017-07-27 10:42:41
【问题描述】:

如果将任何键/值传递给它,我有以下函数将给我随机字符串。

现在我想要这样,如果我将相同的键/值传递给该函数,那么它将给我与之前生成的相同的字符串。

例如。如果我传递字符串 "iv3mw" 那么它将返回输出,即 "3vmiw" 。现在我想要这样,如果我再次传递相同的字符串“iv3mw”,在这种情况下,我想要与之前相同的输出,即“3vmiw”

请建议我该怎么做。下面是我的代码

 public string RandomString(string key = "")
    {
        string input = "";
        if (key.Trim() == "")
        {
            input = "abcdefghijklmnopqrstuvwxyz0123456789";
        }
        else
        {
            input = key;
        }
        var chars = Enumerable.Range(0, 5)
                               .Select(x => input[random.Next(0, input.Length)]);
        return new string(chars.ToArray());
    }

【问题讨论】:

  • 一个 RandomString 函数,根据一个键生成相同的输出,不就是一种哈希函数吗?
  • 如果您想要一致的输出,也许某种散列函数会更好。已经有很多可用的了。不过,这取决于您使用它的目的。
  • Random 构造函数必须使用相同的种子
  • 与您的实际问题无关,但您是否希望这会产生输入中字母的随机排序或输入中字母的随机字母样本串?即你知道abcde 的输入会产生aaaaa 的输出吗?

标签: c# .net c#-4.0


【解决方案1】:

您可以在创建而不是 Random 时传入种子。相同的种子将始终生成相同的随机数序列。种子是一个数字,因此您需要一种从字符串到数字的方法。这是一个有效的实现:

public string RandomString(string key = "")
{
    var random = new Random(key.GetHashCode());
    string input = "";
    if (key.Trim() == "")
    {
        input = "abcdefghijklmnopqrstuvwxyz0123456789";
    }
    else
    {
        input = key;
    }
    var chars = Enumerable.Range(0, 5)
                           .Select(x => input[random.Next(0, input.Length)]);
    return new string(chars.ToArray());
}

您可以看到我使用key.GetHashCode() 播种了Random。这是从字符串中获取 int 的一种快速而肮脏的方法。您应该评估它是否适合您使用它的任何目的。

值得一提的是,我认为不能依赖GetHashCode 在不同的系统或同一程序的不同执行中给出相同的值。可能会,但不能保证,所以如果这是一个问题,您需要将自己的字符串写入 int 函数。

【讨论】:

  • GetHashCode 不应该用于 .NET 中的持久性,它只能保证在同一个 AppDomain 中是“稳定的”。如果这就是 OP 的全部需求,那很好;如果他还需要跨域/应用程序运行/不同计算机持续存在的东西,他将需要自己的哈希函数作为种子。
  • @Luaan:这似乎在我的最后一段中有所涉及(这是在最初的帖子之后添加的,以防你认为你快疯了,因为帖子没有列出编辑)
  • @Chirs :在我的情况下,假设我传递字符串 "iv3mw" 那么它将返回输出,即 "3vmiw" 。现在我想要这样,如果我再次传递相同的字符串“iv3mw”,在这种情况下我想要与之前相同的输出,即“3vmiw”。
  • Err.... 你的输入是“iw3vm”,你的输出是“iv3mw”。它们在哪些方面是相同的?
  • 你是说它为相同的输入产生不同的输出,还是它产生与你的原始程序不同的输出?我不确定“3vmiw”如何适合这里的东西......
【解决方案2】:

MD5 哈希对相同的输入产生相同的输出,从而确保您的一致性。

一个简单的例子

using System.Security.Cryptography;
using (MD5 md5Hash = MD5.Create())
{
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(source));
        StringBuilder sBuilder = new StringBuilder();

        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        return sBuilder.ToString();                
}

【讨论】:

    【解决方案3】:

    您可以缓存已经生成的值。

    Dictionary<string, string> cache = new Dictionary<string, string>
    
    public string RandomString(string key = "")
    {
        string input = "";
        if (key.Trim() == "")
        {
            input = "abcdefghijklmnopqrstuvwxyz0123456789";
        }
        else
        {
            input = key;
        }
    
        if (cache.ContainsKey(input))
        {
            return cache[input];
        }
        else
        {
            var chars = Enumerable.Range(0, 5)                               
                .Select(x => input[random.Next(0, input.Length)]);
            var value = chars.ToArray();
            cache[input] = value;
            return value;
        }
    }
    

    警告

    正如 Chris 在他的评论中提到的,这不会在程序的多次运行之间产生一致的结果。

    【讨论】:

    • 值得一提的是,这不会在程序的多次运行之间产生一致的结果。这可能是也可能不是问题,但值得一提。
    • 很好,我没想到。
    【解决方案4】:

    你在哪里声明“随机”变量?

    我猜你的随机变量是 System.Random 类的一个实例。该类有 2 个构造函数:一个没有参数,另一个带有 Int32 参数(随机种子值)。如果使用第二个构造函数(设置种子值的构造函数),每次使用相同的种子值都会获得相同的随机数序列(因此,相同的 RandomString)。

    希望对您有所帮助。

    【讨论】:

    • 我已经在类级别声明了随机变量
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 2015-09-27
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多