Skip to content

Instantly share code, notes, and snippets.

@GrabYourPitchforks
Last active December 16, 2025 19:05
Show Gist options
  • Select an option

  • Save GrabYourPitchforks/2a68fff33cd9d291aaf739e738ce5d73 to your computer and use it in GitHub Desktop.

Select an option

Save GrabYourPitchforks/2a68fff33cd9d291aaf739e738ce5d73 to your computer and use it in GitHub Desktop.
Downlevel implementation of RandomNumberGenerator.GetInt32
// Adapted from https://github.com/dotnet/corefx/pull/31243
// Please see license information at https://github.com/dotnet/runtime/blob/main/LICENSE.TXT
using System;
using System.Security.Cryptography;
public static class RandomNumberGeneratorExtensions
{
public static int GetInt32(this RandomNumberGenerator csprng, int fromInclusive, int toExclusive)
{
if (fromInclusive >= toExclusive)
throw new ArgumentException("Bad from / to values.");
// The total possible range is [0, 4,294,967,295).
// Subtract one to account for zero being an actual possibility.
uint range = (uint)toExclusive - (uint)fromInclusive - 1;
// If there is only one possible choice, nothing random will actually happen, so return
// the only possibility.
if (range == 0)
{
return fromInclusive;
}
// Create a mask for the bits that we care about for the range. The other bits will be
// masked away.
uint mask = range;
mask |= mask >> 1;
mask |= mask >> 2;
mask |= mask >> 4;
mask |= mask >> 8;
mask |= mask >> 16;
byte[] bytes = new byte[sizeof(uint)];
uint result;
do
{
csprng.GetBytes(bytes);
result = mask & BitConverter.ToUInt32(bytes, 0);
}
while (result > range);
return (int)result + fromInclusive;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment