Comments and answers for "What algorithm does RAND() in SQL Server use?"
https://ask.sqlservercentral.com/questions/2981/what-algorithm-does-rand-in-sql-server-use.html
The latest comments and answers for the question "What algorithm does RAND() in SQL Server use?"Comment by tyloman on tyloman's answer
https://ask.sqlservercentral.com/comments/141817/view.html
I have test your statement "Also RAND() alwasys returns same value first time after SQL Server restart, if I remember correctly." and I believe it is not true.Tue, 31 Jan 2017 09:31:27 GMTtylomanComment by tyloman on tyloman's answer
https://ask.sqlservercentral.com/comments/141818/view.html
Your algorithm works for seeded numbers but it does not work for Rand() call without any seed. Any idea?Tue, 31 Jan 2017 08:25:24 GMTtylomanComment by SQL Kiwi
https://ask.sqlservercentral.com/comments/86149/view.html
According to the "Using RAND" Books Online entry:
*"The RAND function is a pseudorandom number generator that operates in a manner similar to the C run-time library rand function"*
The (non-mersenne!) twist there is that Microsoft don't provide source code for their implementation of the stdlib rand function. The answer provided by @paganaye looks very plausible. Might be a http://en.wikipedia.org/wiki/Multiply-with-carry implementation?Thu, 02 Feb 2012 10:29:25 GMTSQL KiwiComment by Oleg on Oleg's answer
https://ask.sqlservercentral.com/comments/86118/view.html
@paganaye How can this line possibly work?
<pre>const double RAND_DIVIDER = 2147483589.4672801884116202;</pre>
Double numbers are approximate and cannot possibly have more than 15 (sometimes 16) accurate digits, so
<pre>double a = 2147483589.4672801884116202;
double b = 2147483589.46728017;
double c = 2147483589.46728013;
Console.WriteLine("a equal to b: " + (a == b).ToString());
Console.WriteLine("b equal to c: " + (b == c).ToString());
Console.WriteLine("a equal to c: " + (a == c).ToString());
Console.ReadLine();</pre>
The above produces true for all of them.Wed, 01 Feb 2012 17:02:32 GMTOlegAnswer by paganaye
https://ask.sqlservercentral.com/answers/86088/view.html
Here is my attempt to guessing the Algorithm used in SQL Rand()
This algorithm returns the same value than SQL on my machine.
Let me know if this works with you.
This is C# code.
public class SQLRand
{
private static int n1;
private static int n2;
#region "PRIVATE METHODS"
private static void ShiftAndCarry(ref int n, int LEQA, Int64 MULTIPLIER, int SHIFT, int MODULUS)
{
n = n * LEQA - ((int)(n * MULTIPLIER >> SHIFT)) * MODULUS;
if (n < 0) n += MODULUS;
}
private static int IntRand()
{
ShiftAndCarry(ref n1,
LEQA: 40014,
MULTIPLIER: 327796565,
SHIFT: 44,
MODULUS: 2147483563); // The 105,097,561st prime
ShiftAndCarry(ref n2,
LEQA: 40692,
MULTIPLIER: 1333397965,
SHIFT: 46,
MODULUS: 2147483399); // the 105,097,554th prime
// We used two of the bigger prime that would fit a C# integer.
// The biggest prime number that would fit is int.MaxValue = 2^31 - 1 = 2,147,483,647 (the 105,097,565th prime)
int result = n1 - n2;
if (result < 1) result += (2147483563 - 1); // same modulo than for n1
return result;
}
#endregion "PRIVATE METHODS"
/// <summary>
/// Returns a pseudo-random number.
/// </summary>
/// <returns>double value from 0 through 1, exclusive</returns>
public static double Rand()
{
const double RAND_DIVIDER = 2147483589.4672801884116202;
return IntRand() / RAND_DIVIDER;
}
/// <summary>
/// Initiate the pseudo-random number generator using a seed, and return a 'not-so-random' first value.
/// </summary>
/// <param name="seed">Seed is an integer that fixes the returned value and subsquent calls.</param>
/// <returns>double value from 0 through 1, exclusive</returns>
public static double Rand(int seed)
{
n1 = (seed < 0 ? -seed : seed == 0 ? 12345 : seed);
n2 = 67890;
return Rand();
}
}Wed, 01 Feb 2012 11:26:14 GMTpaganayeComment by Bob Hovious on Bob Hovious's answer
https://ask.sqlservercentral.com/comments/9989/view.html
From BOL:
Repetitive calls of RAND() with the same seed value return the same results.
For one connection, if RAND() is called with a specified seed value, all subsequent calls of RAND() produce results based on the seeded RAND() call. For example, the following query will always return the same sequence of numbers.Sat, 14 Nov 2009 11:29:14 GMTBob HoviousComment by Blackhawk-17
https://ask.sqlservercentral.com/comments/9975/view.html
Neat question! The follow up is "What difference would it make?"Fri, 13 Nov 2009 16:49:17 GMTBlackhawk-17Answer by Peso
https://ask.sqlservercentral.com/answers/2995/view.html
<p>I wouldn't use RAND. Nowadays I use ABS(CHECKSUM(NEWID())) % 1000 to get random number between 0 and 999. It has better distribution than RAND().
Also RAND() alwasys returns same value first time after SQL Server restart, if I remember correctly.</p>Fri, 13 Nov 2009 16:48:39 GMTPesoComment by Matt Whitfield
https://ask.sqlservercentral.com/comments/9972/view.html
Now that *is* a good question!Fri, 13 Nov 2009 16:41:35 GMTMatt Whitfield