【问题标题】:c# Generate Random number passing long as seed instead of int32c#生成随机数作为种子而不是int32传递
【发布时间】:2019-10-24 14:26:09
【问题描述】:

c# Generate Random number 传递 long 作为种子而不是 int32,但我需要传递电话号码或帐号

https://docs.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8#System_Random__ctor_System_Int32_

请推荐任何可靠的 NuGet 包,或者任何已经做过类似事情的实现。

我需要将完整的 PhoneNumber 作为种子传递,我可以在 python 中但不能使用 C#,并且我的代码堆栈都在 C# 中

使用系统;

public class Program
{
    public static void Main()
    {
            int seed = 0123456789;
            Random random = new Random(seed);
            double result = random.NextDouble();
            Console.WriteLine(result);
    }
}

对我的要求和我想要实现的目标的一些见解:

1)We're doing this for A/B testing and todo data analysis on the 
  experience of two services. 

2)When a request comes with
  phoneNumber based on random.NextDouble() there is a preset percentage
  which we use to determine whether to send a request to service A or
  service B 

3)For example, let's says the request comes and falls
 under >0.5 then we direct the request to service A and the next time
 the request with the same phone number comes in it will be >0.5 and
 goes service A since the seed is a unique hash of phoneNumber.

【问题讨论】:

  • 没有构造函数接受Int64 种子。要么将所需的值作为种子转换为 Int32,要么使用 .NET Core 提供的 Random 类以外的其他东西。
  • 我怀疑你是否理解 seed 的用途。给定某个seed 值,典型的随机生成器将根据该种子生成一个固定的数字序列。下次您使用相同的 seed 创建 Rnd 生成器对象时,将生成 相同的 FIXED 序列。无论使用intlong 作为种子,这都是正确的。演示:dotnetfiddle.net/TQQm6l
  • 请记住,多个唯一的 long 值可以映射到同一个 int 值。至于转换,您可以这样做:int seed = (int)(someLongValue % int.MaxValue);
  • @inan 我的意思不是可能有重复的电话号码,而是两个唯一的电话号码可能映射到相同的种子值。假设我有 longA 和 longB,其中 longA != longB。但是,如果您计算它们各自的seedA 和seedB,那么seedA == seedB 可能会发生。此外,您还没有真正向我们提供有关在您的应用程序中使用它的方式和目标的任何信息,因此很难确定哪种方法会更好。

标签: c# .net .net-core


【解决方案1】:

GetHashCode()方法属于Object类,与随机数生成无关。请在此处阅读 (https://docs.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=netframework-4.8)。文档明确指出,如果输入一致,则可能会发生冲突。

HashAlgorithm.ComputeHash 方法(此处记录 - https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.hashalgorithm.computehash?view=netframework-4.8)计算给定值的哈希值,但它本质上是一致的,即如果输入相同,则生成的输出也相同。显然这不是所需的输出(我假设)。我附上了我尝试生成的示例代码。

static void Main(string[] args)
{

    Console.WriteLine("Hello World!");

    while (true)
    {
        Console.WriteLine("Enter a 9 digit+ number to calculate hash");
        var val = Console.ReadLine();
        long target = 0;
        bool result = long.TryParse(val,out target);
        if (result)
        {
            var calculatedHash = OutputHash(target);

            Console.WriteLine("Calculated hash is : " + calculatedHash);
        }
        else
        {
            Console.WriteLine("Incorrect input. Please try again.");
        }
    }
}

public static string OutputHash(long number)
{
    string source = Convert.ToString(number);
    string hash;

    using (SHA256 sha256Hash = SHA256.Create())
    {
        hash = GetHash(sha256Hash, source);

        Console.WriteLine($"The SHA256 hash of {source} is: {hash}.");

        Console.WriteLine("Verifying the hash...");

        if (VerifyHash(sha256Hash, source, hash))
        {
            Console.WriteLine("The hashes are the same.");
        }
        else
        {
            Console.WriteLine("The hashes are not same.");
        }
    }

    return hash;
}

private static string GetHash(HashAlgorithm hashAlgorithm, string input)
{

    // Convert the input string to a byte array and compute the hash.
    byte[] data = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(input));

    // Create a new Stringbuilder to collect the bytes
    // and create a string.
    var sBuilder = new StringBuilder();

    // Loop through each byte of the hashed data 
    // and format each one as a hexadecimal string.
    for (int i = 0; i < data.Length; i++)
    {
        sBuilder.Append(data[i].ToString("x2"));
    }

    // Return the hexadecimal string.
    return sBuilder.ToString();
}

// Verify a hash against a string.
private static bool VerifyHash(HashAlgorithm hashAlgorithm, string input, string hash)
{
    // Hash the input.
    var hashOfInput = GetHash(hashAlgorithm, input);

    // Create a StringComparer an compare the hashes.
    StringComparer comparer = StringComparer.OrdinalIgnoreCase;

    return comparer.Compare(hashOfInput, hash) == 0;
}

我同意上面@Knoop 的评论,您可能最终会得到相同的整数映射到多个长数字输入值。

如果您正在寻找具有长值作为种子的“纯”随机数生成器,您别无选择,只能选择第三方库(或实现您自己的自定义算法)。然而,与其陷入如此复杂的境地,不如简单

Guid g = Guid.NewGuid();

应该可以解决问题 (https://docs.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=netframework-4.8)。 文档 (https://docs.microsoft.com/en-gb/windows/win32/api/combaseapi/nf-combaseapi-cocreateguid?redirectedfrom=MSDN ) 说,即使这样最终也会发生冲突,但机会非常小。

最后,这听起来像是.NET unique object identifier的潜在重复

【讨论】:

    【解决方案2】:

    取电话号码的哈希值,例如:

    var phoneNumber = 123456789L;
    var seed = phoneNumber.GetHashCode();
    

    这意味着对于相同的电话号码,您将获得相同的序列。这也意味着对于某些电话号码,您将获得相同的序列,但这会很渺茫。正如所评论的那样,在不同的 .net 运行时可能会有所不同,但您可能不在乎。

    不确定您为什么要这样做,但我有原因,例如测试代码

    【讨论】:

    • 如果需要这样来预测 RNG 的结果,散列不能保证在框架版本之间产生相同的结果,the documentation 有一些关于做什么的评论(以及 to do) 使用哈希。
    猜你喜欢
    • 2011-02-08
    • 2021-05-15
    • 1970-01-01
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2020-12-15
    • 1970-01-01
    相关资源
    最近更新 更多