C++随机数

这篇博客探讨了C++11引入的新版随机数功能,介绍了一个基类`Random`及其派生类`RandomAvg`、`RandomNorm`和`RandomItem`。`Random`用于生成随机数种子,确保线程安全;`RandomAvg`生成平均分布的随机数,`RandomNorm`生成正态分布的随机数,而`RandomItem`则根据权重从奖池中随机选择元素。博客还包含了相关源代码示例。
摘要由CSDN通过智能技术生成

待着无聊,我又开始乱敲代码了。
这次是:随机数。。。
这里用到了C++11的新版随机数,感觉……还可以?

以下代码都是瞎写的
以下代码能够正常工作但不是最新的。我又进行了性能上的改动。(2018.9.20)

基类 Random,静态类,其中所有的函数都为静态函数。它的作用主要是生成一个随机数种子。
随机数种子的是自从执行代码的机器开机到执行时刻所经历的微秒数。一旦CPU不支持QueryPerformanceFrequency的API函数,那么则用当前时间的毫秒数作为种子。
此类是线程安全的。
每当获取的随机数数量达到一个周期,则重新获得种子。
获取每个随机数都不是顺序获取的。每获取一个,都会抛弃未知个之后的随机数(baseGener.discard 函数生效)。

派生类 RandomAvg,静态类,并且此类不能够被继承。它的作用是生成一个平均分布的随机数。
其中 HitProbability 函数表示,输入一个小于1.0的概率值,返回 bool。true表示命中了概率,false表示没有命中。
其中 HitExpectation 函数表示,输入一个小于1.0的期望概率值,返回无符号int,表示连续几次才能命中一次期望概率。例子,英雄联盟一个英雄在一场游戏的某个时刻的面板暴击率为20%,那么,他第一刀暴击的概率为20%;若没有出现暴击,则第二刀暴击概率为40%,以此类推,直到他出现暴击。也就是说,输入一个期望概率probExp,则在ceil(1.0/probExp)次中至少出现一次命中。

派生类 RandomNorm,非静态类,并且此类不能够被继承。它的作用是生成一个正态分布的随机数。构造函数的参数1为平均值,参数2是标准差。注意,返回的随机值并不是根据给定的随机X输出Y。具体百度“正态分布”。

派生类 RandomItem,非静态类,模板类,并且此类不能够被继承。它的作用是给定一个奖池vector,根据奖池中每一个奖励的权值来随机奖励。模版类型是结构体,里面应该包括奖励信息和一个奖励权值。构造函数的参数1为奖池,参数2为如何从奖励结构体中返回权值的函数,此函数用法在mian.cpp中提供了示例。之所以没有实现成静态类是由于效率考虑。参考static const ItemT& GetRandItem(const std::vector& items, const std::function<uint64_t(const ItemT&)>& GetWeightFunc);函数,每次随机一次奖励都要重新计算总权值和权值区间,所以不建议在多次抽奖的循环中使用此静态方法。

Random.h

#include "stdinc.h"

#include <CoreWindow.h>
#include <random>
#include <atomic>
#include <functional>

#include <map>

#pragma once
class Random
{
    
protected:
	static std::mt19937_64 baseGener;

	static LARGE_INTEGER sysTime;
	static std::atomic<uint64_t> ranCount;
	static const uint64_t RandBase;

public:
	Random();
	~Random();

public:
	static void Init();
	static void Reset();

	static uint64_t GetRandNum();

protected:
	static void SyncSeed();	
};

class RandomAvg final : public Random
{
    
public:
	RandomAvg();
	~RandomAvg();
	static void Init();
	static void Reset();

public:
	static uint64_t GetAveNum();
	static uint64_t GetAveNum(const uint64_t& min, const uint64_t& max); //Return [min, max).

	static bool HitProbability(const double& prob);
	static uint64_t HitExpectation(const double& probExp);

private:
	static std::uniform_int_distribution<uint64_t> avgNum;
};

class RandomNorm final : public Random
{
    
private:
	long double _avg;
	long double _stdDev;

public:
	RandomNorm();
	RandomNorm(long double avg, long double stdDev);

	~RandomNorm();

public:
	void Init(const long double& avg, const long double& stdDev);
	void Reset();
	void Clear();

public:
	template<typename RetT = long double>
	RetT GetNormNum();

private:
	std::normal_distribution<long double>* ptrNormNum = nullptr;
};

template<typename ItemT>
class RandomItem final : public Random
{
    
public:
	RandomItem() = delete;
	RandomItem(const std::vector<ItemT>& items, const std::function<uint64_t(const ItemT&)>& GetWeightFunc);
	~RandomItem();

public:
	void Init(const std::vector<ItemT>& items, const std::function<uint64_t(const ItemT&)>& GetWeightFunc);
	void Reset() = delete;
	void Clear();

public:
	static const ItemT& GetRandItem(const std::vector<ItemT>& items, const std::function<uint64_t(const ItemT&)>& GetWeightFunc);
	const ItemT& GetRandItem();
	const uint64
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值