Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Random number in long range, is this the way?

Tags:

random

c#-4.0

Can somebody verify this method. I need a long type number inside a range of two longs. I use the .NET Random.Next(min, max) function which return int's. Is my reasoning correct if I simply divide the long by 2, generate the random number and finally multiply it by 2 again? Or am I too enthusiastic... I understand that my random resolution will decrease but are there any other mistakes which will lead to no such a random number.

long min = st.MinimumTime.Ticks;    //long is Signed 64-bit integer long max = st.MaximumTime.Ticks; int minInt = (int) (min / 2);      //int is Signed 64-bit integer int maxInt = (int) (max / 2);      //int is Signed 64-bit integer  Random random = new Random(); int randomInt = random.Next(minInt, maxInt); long randomLong = (randomInt * 2); 
like image 979
Nick V Avatar asked Jul 11 '11 14:07

Nick V


People also ask

Why is 17 the most common random number?

Seventeen is: Described at MIT as 'the least random number', according to the Jargon File. This is supposedly because in a study where respondents were asked to choose a random number from 1 to 20, 17 was the most common choice. This study has been repeated a number of times.

What is meant by random number?

What is a random number? As the term suggests, a random number is a number chosen by chance -- i.e., randomly, from a set of numbers. All the numbers in a specified distribution have equal probability of being chosen randomly.

What is the most common random number?

We are told that MIPS chip designer Mark Johnson, who claims it is the World's most common random number, is responsible for scribbling this number onto the mask. A number of visitors have responded to us about the concept of 37 being the most random number.


2 Answers

Why don't you just generate two random Int32 values and make one Int64 out of them?

long LongRandom(long min, long max, Random rand) {     long result = rand.Next((Int32)(min >> 32), (Int32)(max >> 32));     result = (result << 32);     result = result | (long)rand.Next((Int32)min, (Int32)max);     return result; } 

Sorry, I forgot to add boundaries the first time. Added min and max params. You can test it like that:

long r = LongRandom(100000000000000000, 100000000000000050, new Random()); 

Values of r will lie in the desired range.

EDIT: the implementation above is flawed. It's probably worth it to generate 4 16-bit integers rather than 2 32-bit ones to avoid signed-unsigned problems. But at this point the solution loses its elegancy, so I think it's best to stick with Random.NextBytes version:

long LongRandom(long min, long max, Random rand) {     byte[] buf = new byte[8];     rand.NextBytes(buf);     long longRand = BitConverter.ToInt64(buf, 0);      return (Math.Abs(longRand % (max - min)) + min); } 

It looks pretty well in terms of value distribution (judging by very simple tests I ran).

like image 78
Dyppl Avatar answered Sep 28 '22 10:09

Dyppl


Some other answers here have two issues: having a modulo bias, and failing to correctly handle values of max = long.MaxValue. (Martin's answer has neither problem, but his code is unreasonably slow with large ranges.)

The following code will fix all of those issues:

//Working with ulong so that modulo works correctly with values > long.MaxValue ulong uRange = (ulong)(max - min);  //Prevent a modolo bias; see https://stackoverflow.com/a/10984975/238419 //for more information. //In the worst case, the expected number of calls is 2 (though usually it's //much closer to 1) so this loop doesn't really hurt performance at all. ulong ulongRand; do {     byte[] buf = new byte[8];     random.NextBytes(buf);     ulongRand = (ulong)BitConverter.ToInt64(buf, 0); } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange);  return (long)(ulongRand % uRange) + min; 

The following fully-documented class can be dropped into your codebase to implement the above solution easily and brain-free. Like all code on Stackoverflow, it's licensed under CC-attribution, so you can feel free to use to use it for basically whatever you want.

using System;  namespace MyNamespace {     public static class RandomExtensionMethods     {         /// <summary>         /// Returns a random long from min (inclusive) to max (exclusive)         /// </summary>         /// <param name="random">The given random instance</param>         /// <param name="min">The inclusive minimum bound</param>         /// <param name="max">The exclusive maximum bound.  Must be greater than min</param>         public static long NextLong(this Random random, long min, long max)         {             if (max <= min)                 throw new ArgumentOutOfRangeException("max", "max must be > min!");              //Working with ulong so that modulo works correctly with values > long.MaxValue             ulong uRange = (ulong)(max - min);              //Prevent a modolo bias; see https://stackoverflow.com/a/10984975/238419             //for more information.             //In the worst case, the expected number of calls is 2 (though usually it's             //much closer to 1) so this loop doesn't really hurt performance at all.             ulong ulongRand;             do             {                 byte[] buf = new byte[8];                 random.NextBytes(buf);                 ulongRand = (ulong)BitConverter.ToInt64(buf, 0);             } while (ulongRand > ulong.MaxValue - ((ulong.MaxValue % uRange) + 1) % uRange);              return (long)(ulongRand % uRange) + min;         }          /// <summary>         /// Returns a random long from 0 (inclusive) to max (exclusive)         /// </summary>         /// <param name="random">The given random instance</param>         /// <param name="max">The exclusive maximum bound.  Must be greater than 0</param>         public static long NextLong(this Random random, long max)         {             return random.NextLong(0, max);         }          /// <summary>         /// Returns a random long over all possible values of long (except long.MaxValue, similar to         /// random.Next())         /// </summary>         /// <param name="random">The given random instance</param>         public static long NextLong(this Random random)         {             return random.NextLong(long.MinValue, long.MaxValue);         }     } } 

Usage:

Random random = new Random(); long foobar = random.NextLong(0, 1234567890L); 
like image 45
BlueRaja - Danny Pflughoeft Avatar answered Sep 28 '22 09:09

BlueRaja - Danny Pflughoeft