Last active
December 16, 2025 19:05
-
-
Save GrabYourPitchforks/2a68fff33cd9d291aaf739e738ce5d73 to your computer and use it in GitHub Desktop.
Downlevel implementation of RandomNumberGenerator.GetInt32
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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