Random Number

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

 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注