-6

I want to generate a secure random number using SFMT prng library in c#, but it's not working for long int (for >= 19 digit number). Please give me a hint about how to use SFMT PRNG (mersenne twister) for long int in C# ?

Randoms.next(int min,int max); But how to use for long int ?

Getaw Dejen
  • 341
  • 1
  • 4
  • 13
  • Generate two 10-digit numbers and join them together? – Ken Y-N Sep 19 '17 at 07:59
  • 6
    What does *not working* mean? Show your code and what results you get and what you expect instead. – MakePeaceGreatAgain Sep 19 '17 at 07:59
  • @KenY-N probably such methods have lower mathematical quality (dispersion, randomness etc) – Jacek Cz Sep 19 '17 at 08:01
  • 2
    Long integers in C# are signed 64 bit integers, and as such limited to 19 digits (see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/long). Depending on what you're going to use the number for, you could perhaps generate a string of random numbers whatever length you require, rather than a single large number. – Diado Sep 19 '17 at 08:03
  • Randoms.next(1000000000000000,9999999999999999999); – Getaw Dejen Sep 19 '17 at 08:03
  • @JacekCz I suppose the answer should depend on the number of bytes; but don't most crypto libraries have a call to return *n* random bytes, which is what the OP should be using rather than arbitrarily pasting two shorter numbers together. – Ken Y-N Sep 19 '17 at 08:04
  • Use an RNG to generate 8-9 random bytes e.g. with a NextBytes like function. – apokryfos Sep 19 '17 at 08:09
  • Randoms.next(int min,int max) but how to use for long int min and max ? – Getaw Dejen Sep 19 '17 at 08:14
  • `9999999999999999999` doesn't fit in a `long`, but it does fit in a `ulong` - so you'll need to use `ulong` for this. – Matthew Watson Sep 19 '17 at 08:54

1 Answers1

3

You can write extension methods for Random as follows:

public static class RandomExt
{
    public static long NextLong(this Random self, long min, long max)
    {
        // Get a random 64 bit number.

        var buf = new byte[sizeof(ulong)];
        self.NextBytes(buf);
        ulong n = BitConverter.ToUInt64(buf, 0);

        // Scale to between 0 inclusive and 1 exclusive; i.e. [0,1).

        double normalised = n / (ulong.MaxValue + 1.0);

        // Determine result by scaling range and adding minimum.

        double range = (double)max - min;

        return (long)(normalised * range) + min;
    }

    public static ulong NextULong(this Random self, ulong min, ulong max)
    {
        // Get a random 64 bit number.

        var buf = new byte[sizeof(ulong)];
        self.NextBytes(buf);
        ulong n = BitConverter.ToUInt64(buf, 0);

        // Scale to between 0 inclusive and 1 exclusive; i.e. [0,1).

        double normalised = n / (ulong.MaxValue + 1.0);

        // Determine result by scaling range and adding minimum.

        double range = (double)max - min;

        return (ulong)(normalised * range) + min;
    }
}

(The algorithm I used to create a random double in the range [0,1) is the same as that used by the Random class, except I converted it to use ulong rather than ushort.)

Then you can do this:

var rng = new Random();
ulong randomNumber = rng.NextULong(1000000000000000, 9999999999999999999);

Ideally you'd use a better random number generator (such as an XOR-SHIFT) with a longer period, but this will give you random numbers in the specified range.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276