XorShiftRandom Class
Definition
Represents a high-performance, non-cryptographic pseudo-random number generator based on Marsaglia's xorshift128 algorithm.
public sealed class XorShiftRandom : Random, IRandomGenerator
- Inheritance
-
XorShiftRandom
- Implements
- Inherited Members
- Extension Methods
Examples
// Reproducible shuffle and sample in a test.
var rng = new XorShiftRandom(seed: 1234);
int roll = rng.Next(6) + 1; // value in [1, 6]
double angle = rng.NextDouble() * Math.Tau;
var bag = new[] { "A", "B", "C", "D" };
ShuffleHelpers.Shuffle(bag, rng);
Remarks
XorShiftRandom derives each output by combining four 32-bit state words through three xor-and-shift operations - a generator class introduced by George Marsaglia in 2003. The cost per draw is a handful of register operations with no branching, no division, and no memory allocation, making it materially faster than Random in tight inner loops on every supported runtime.
The type subclasses Random so it can be passed anywhere Random is accepted, and it also implements IRandomGenerator for use with the library's shuffle and sampling helpers. The default constructor seeds from TickCount; the seeded constructors are the preferred choice in tests and reproducible benchmarks.
Instances are not thread-safe - state updates are non-atomic and concurrent draws will corrupt the internal state. Use a per-thread instance, an external lock, or a thread-local pool when sharing across threads is required.
The algorithm produces a uniform distribution over the 32-bit output range and has a period of 2^128 − 1. It
is not suitable for cryptographic use, secret material, or any context where an attacker can observe
outputs and recover state. Use System.Security.Cryptography.RandomNumberGenerator for those cases.
Constructors
XorShiftRandom()
Initializes a new instance of the XorShiftRandom class using a system-generated seed.
public XorShiftRandom()
Remarks
The default seed is derived from TickCount at the time of construction.
TickCount has finite resolution (commonly ~15.6 ms on Windows, finer on Linux), so two XorShiftRandom instances created back-to-back within the same tick will observe the same seed and therefore yield identical sequences. This is a deliberate trade-off for the cheapest possible default seeding on a non-cryptographic PRNG. Callers that require either guarantee should use a different constructor:
- For reproducibility (tests, benchmarks, replayable simulations) use XorShiftRandom(int) or XorShiftRandom(uint) with an explicit seed.
-
For distinct sequences across many instances derive the seed from Shared
(e.g.
new XorShiftRandom(Random.Shared.Next())) or, when stronger entropy is required, from System.Security.Cryptography.RandomNumberGenerator.
XorShiftRandom(int)
Initializes a new instance of the XorShiftRandom class with a 32-bit signed integer seed.
public XorShiftRandom(int seed)
Parameters
seedintThe seed used to initialize the random generator.
XorShiftRandom(uint)
Initializes a new instance of the XorShiftRandom class with a 32-bit unsigned seed.
public XorShiftRandom(uint seed)
Parameters
seeduintThe seed used to initialize the random generator.
Methods
Next()
Returns a non-negative random integer.
public override int Next()
Returns
- int
A 32-bit signed integer that is greater than or equal to 0 and less than Int32.MaxValue.
Next(int)
Returns a non-negative random integer that is strictly less than the specified exclusive upper bound.
public override int Next(int maxValue)
Parameters
maxValueintThe exclusive upper bound of the random number to be generated.
Returns
- int
A 32-bit signed integer in the half-open interval
[0,.maxValue)
Remarks
Matches the contract of Next(int). Draws are produced through Lemire-style rejection rather than modulo, eliminating the modulo-bias that would otherwise skew small bounds.
Exceptions
- ArgumentOutOfRangeException
maxValueis less than or equal to zero.
Next(int, int)
Returns a random integer in the half-open interval
[.minValue, maxValue)
public override int Next(int minValue, int maxValue)
Parameters
minValueintThe inclusive lower bound of the random number to be generated.
maxValueintThe exclusive upper bound of the random number to be generated.
Returns
- int
A 32-bit signed integer greater than or equal to
minValueand strictly less thanmaxValue; orminValuewhen the two bounds are equal.
Remarks
Matches the contract of Next(int, int), including its handling of an empty range:
when minValue equals maxValue the method returns
minValue without throwing. Only a strictly inverted range (minValue >
maxValue) raises ArgumentException.
The full int span Next(int.MinValue, int.MaxValue) is supported - the range is computed in
64-bit space so the subtraction never overflows, and bounded generation uses Lemire-style rejection rather than
modulo to avoid modulo-bias.
Exceptions
- ArgumentException
minValueis strictly greater thanmaxValue.
NextBytes(byte[])
Fills the elements of a specified array of bytes with random numbers.
public override void NextBytes(byte[] buffer)
Parameters
bufferbyte[]The array to be filled with random numbers.
Exceptions
- ArgumentNullException
bufferis null.
NextBytes(Span<byte>)
Fills the elements of a specified span of bytes with random numbers.
public override void NextBytes(Span<byte> buffer)
Parameters
Remarks
The span is filled from consecutive 32-bit draws, four bytes per draw in little-endian order, with a trailing partial chunk taking the low-order bytes of one final draw. The packing is identical to NextBytes(byte[]), so for the same seed and length both overloads produce the same bytes.
NextDouble()
Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0.
public override double NextDouble()
Returns
- double
A double-precision floating point number that is greater than or equal to 0.0, and less than 1.0.
Remarks
The result is derived from a single 32-bit draw, so it has 32-bit granularity: only 2^32 distinct values
are possible, spaced 2^-32 apart, rather than the 2^53 values a full-precision
double in [0, 1) could represent. This is sufficient for shuffling, sampling, and similar
non-cryptographic uses; callers needing finer-grained doubles should compose them from two draws.
NextInt64()
Returns a non-negative random integer.
public override long NextInt64()
Returns
- long
A 64-bit signed integer that is greater than or equal to 0 and less than Int64.MaxValue.
Remarks
The result is composed from two consecutive 32-bit draws of the generator stream - the first draw supplies the
high word, the second the low word - reduced to 63 bits; a draw equal to MaxValue is
rejected and redrawn so the contractual range [0, long.MaxValue) is preserved without bias.
NextSingle()
Returns a random floating-point number that is greater than or equal to 0.0, and less than 1.0.
public override float NextSingle()
Returns
- float
A single-precision floating point number that is greater than or equal to 0.0, and less than 1.0.
Remarks
Applies to
| Product | Versions |
|---|---|
| .NET | 8, 10 |