C++
#include <cstdint> #if (_WIN32 || _WIN64) #include <Windows.h> #include <bcrypt.h> #pragma comment(lib, "Bcrypt.lib") #else #include <stdio.h> #endif class RandomNumber { public: RandomNumber() { Initialize(); } ~RandomNumber() { #if (_WIN32 || _WIN64) BCryptCloseAlgorithmProvider(phAlgorithm, 0); #else fclose(fd); #endif } RandomNumber(const RandomNumber& randomNumber) = default; RandomNumber(RandomNumber&& randomNumber) noexcept { #if (_WIN32 || _WIN64) BCryptCloseAlgorithmProvider(randomNumber.phAlgorithm, 0); #else fclose(randomNumber.fd); #endif Initialize(); } RandomNumber& operator=(const RandomNumber& randomNumber) = default; RandomNumber& operator=(RandomNumber&& randomNumber) noexcept { #if (_WIN32 || _WIN64) BCryptCloseAlgorithmProvider(randomNumber.phAlgorithm, 0); #else fclose(randomNumber.fd); #endif Initialize(); return *this; } void RandomBytes(uint8_t* buf, const uint32_t len) const { #if (_WIN32 || _WIN64) BCryptGenRandom(phAlgorithm, buf, len, 0); #else for (size_t count = 0, n = 0; count < len; count += n) { n = fread(buf + count, len - count, sizeof(uint8_t), fd); } #endif } uint64_t RandomUint64(const uint64_t min, const uint64_t max) const { union { uint64_t uint64; uint8_t bytes[sizeof(uint64_t)]; } result = { 0 }; if (min == max) return min; const auto dis = max - min + 1; RandomBytes(result.bytes, sizeof(uint64_t)); if (min == 0 && max == UINT64_MAX) { return result.uint64; } if ((dis & dis - 1) != 0) { const auto lim = UINT64_MAX - UINT64_MAX % dis - 1; while (result.uint64 > lim) { RandomBytes(result.bytes, sizeof(uint64_t)); } } return result.uint64 % dis + min; } private: #if (_WIN32 || _WIN64) BCRYPT_ALG_HANDLE phAlgorithm = nullptr; #else FILE* fd; #endif void Initialize() { #if (_WIN32 || _WIN64) BCryptOpenAlgorithmProvider(&phAlgorithm, BCRYPT_RNG_ALGORITHM, nullptr, 0); #else fd = fopen("/dev/urandom", "rb"); #endif } }; #include <cstdio> int main(int argc, char* argv[]) { RandomNumber rn{}; uint32_t count[101] = {0}; for (int i = 0; i < 100000; ++i) { count[rn.RandomUint64(0, 100)]++; } for (int i = 0; i < 101; ++i) { printf("%d:%d\n", i, count[i]); } }
C
#include <stdint.h> #if (_WIN32 || _WIN64) #include <Windows.h> #include <bcrypt.h> #pragma comment(lib, "Bcrypt.lib") #else #include <stdio.h> #endif void RandomBytes(uint8_t* buf, const uint32_t len) { #if (_WIN32 || _WIN64) BCRYPT_ALG_HANDLE phAlgorithm; BCryptOpenAlgorithmProvider(&phAlgorithm, BCRYPT_RNG_ALGORITHM, NULL, 0); BCryptGenRandom(phAlgorithm, buf, len, 0); #else FILE* fd = fopen("/dev/urandom", "rb"); for (size_t count = 0, n = 0; count < len; count += n) { n = fread(buf + count, len - count, sizeof(uint8_t), fd); } fclose(fd); #endif } uint64_t RandomUint64(const uint64_t min, const uint64_t max) { union { uint64_t uint64; uint8_t bytes[sizeof(uint64_t)]; } result = {0}; if (min == max) return min; const uint64_t dis = max - min + 1; RandomBytes(result.bytes, sizeof(uint64_t)); if (min == 0 && max == UINT64_MAX) { return result.uint64; } if ((dis & dis - 1) != 0) { const uint64_t lim = UINT64_MAX - UINT64_MAX % dis - 1; while (result.uint64 > lim) { RandomBytes(result.bytes, sizeof(uint64_t)); } } return result.uint64 % dis + min; } #include <stdio.h> int main(int argc, char* argv[]) { uint32_t count[101] = { 0 }; for (int i = 0; i < 100000; ++i) { count[RandomUint64(0, 100)]++; } for (int i = 0; i < 101; ++i) { printf("%d:%d\n", i, count[i]); } }
F#
class
type RandomNumber() = let csp = new System.Security.Cryptography.RNGCryptoServiceProvider() override this.Finalize() = csp.Dispose() member this.RandomBytes len = let buf = Array.zeroCreate len csp.GetBytes buf buf member this.RandomUint64 min max = let uint64MaxValue = System.UInt64.MaxValue let getRandomUint64 = fun _ -> System.BitConverter.ToUInt64(this.RandomBytes 8, 0) let distance = lazy(max - min + 1UL) if min = max then min elif min = 0UL && max = uint64MaxValue then getRandomUint64() elif distance.Value &&& distance.Value - 1UL = 0UL then getRandomUint64() % distance.Value + min else let limit = uint64MaxValue - uint64MaxValue % distance.Value - 1UL in let result = Seq.initInfinite getRandomUint64 |> Seq.find ((>) limit) in result % distance.Value + min [<EntryPoint>] let main argv = let rn = new RandomNumber() Seq.init 10000 (fun _ -> async{ return rn.RandomUint64 0UL 100UL }) |> Async.Parallel |> Async.RunSynchronously |> Seq.countBy (fun x -> x) |> Seq.sort |> Seq.iter (printfn "%A") 0
module
module RandomNumber = open System.Security.Cryptography let RandomBytes len = let csp = new RNGCryptoServiceProvider() let buf = Array.zeroCreate len csp.GetBytes buf csp.Dispose() buf let RandomUint64 min max = let uint64MaxValue = System.UInt64.MaxValue let getRandomUint64 = fun _ -> System.BitConverter.ToUInt64(RandomBytes 8, 0) let distance = lazy(max - min + 1UL) if min = max then min elif min = 0UL && max = uint64MaxValue then getRandomUint64() elif distance.Value &&& distance.Value - 1UL = 0UL then getRandomUint64() % distance.Value + min else let limit = uint64MaxValue - uint64MaxValue % distance.Value - 1UL in let result = Seq.initInfinite getRandomUint64 |> Seq.find ((>) limit) in result % distance.Value + min [<EntryPoint>] let main argv = Seq.init 10000 (fun _ -> async{ return RandomNumber.RandomUint64 0UL 100UL }) |> Async.Parallel |> Async.RunSynchronously |> Seq.countBy (fun x -> x) |> Seq.sort |> Seq.iter (printfn "%A") 0