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