-2

c# Generate Random number passing long as a seed instead of int32, but l need to pass phone numbers or accounts number

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

Please suggest any reliable NuGet package which does this or any implementation who has already done something like this.

I need to pass the complete PhoneNumber as the seed which I'm able to do in python but not with C# and my code stack is all in C#

using System;

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

Some insights on my requirements and what I'm trying to achieve:

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.
inan
  • 178
  • 11
  • There's no constructor that takes an `Int64` seed. Either you convert the value you want as a seed into an Int32 or you use something other than the Random class provided by .NET Core. – Joe Sewell Oct 24 '19 at 14:33
  • 1
    I doubt if you understand what a `seed` is for. Given a certain `seed` value, a typical random generator will generate a FIXED sequence of numbers based on that seed. The next time you create a Rnd-generator object using that same `seed`, the **same FIXED sequence** is generated. This is true regardless of using an `int` or a `long` for a seed. Demo: https://dotnetfiddle.net/TQQm6l – Peter B Oct 24 '19 at 14:40
  • 1
    Keep in mind that multiple unique long values can map to the same int value. As for a conversion you can just do this: `int seed = (int)(someLongValue % int.MaxValue);` –  Oct 24 '19 at 14:42
  • @inan My point was not that there might be duplicate phone numbers but that 2 unique phonenumbers might map to the same seed value. Lets say I have longA and longB where longA != longB. However if you calculate their respecive seedA and seedB then it might happen that seedA == seedB. Also you've not really given us any information on how and with what goal this is used in your application so it's hard to determine what approach will be better. –  Oct 24 '19 at 15:12

2 Answers2

0

take the hash of the phone number, eg:

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

This means that for the same phoneNumber you will get the same sequence. It also means that for some phone numbers you will get identical sequences, but that is going to be slim. And it might be different on different .net runtimes as commented, but you might not care.

Not sure why you want to, but I there are reasons, e.g. test code

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
mikelegg
  • 1,197
  • 6
  • 10
  • If this is needed to predict the outcome of the RNG, hashing is not guaranteed to produce the same results across framework versions, [the documentation](https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=netframework-4.8#remarks) has some remarks about what to do (and what *not* to do) with hashes. – germi Oct 24 '19 at 14:42
0

The method GetHashCode() belongs to Object class, it has nothing to do with random number generation. Please read here (https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=netframework-4.8). The documentation clearly states that it is possible to get collisions specially if input is consistent.

The method HashAlgorithm.ComputeHash (documented here - https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hashalgorithm.computehash?view=netframework-4.8) calculates the hash for a given value, but it is consistent in nature, i.e. if input is same, generated output is also same. Obviously this is not the desired output (I assume). I have attached the sample code I tried to generate this.

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;
}

I agree with @Knoop 's comment above that you might end up with same integer mapping to multiple long number input values.

If you are looking for a 'pure' random number generator with long value as seed, you don't have a choice but to go for third party libraries (or implementing your own custom algorithm). However, rather than getting into such complexities, simple

Guid g = Guid.NewGuid();

should do the trick (https://learn.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=netframework-4.8). Documentation (https://learn.microsoft.com/en-gb/windows/win32/api/combaseapi/nf-combaseapi-cocreateguid?redirectedfrom=MSDN )says that even this can end up having collisions but chances are very minimal.

Finally, this sounds like potential duplicate of .NET unique object identifier

Amogh Sarpotdar
  • 544
  • 4
  • 15