cpp-toolbox  0.0.1
A toolbox library for C++
Loading...
Searching...
No Matches
random.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <chrono>
5#include <iterator>
6#include <limits>
7#include <random>
8#include <stdexcept>
9#include <vector>
10
12
13namespace toolbox::utils
14{
15
32{
33public:
43 {
44 std::random_device rd;
45 engine_.seed(rd());
46 }
47
55 explicit random_t(unsigned int seed_val)
56 : engine_(seed_val)
57 {
58 }
59
68 {
69 static random_t instance;
70 return instance;
71 }
72
79 void seed()
80 {
81 std::random_device rd;
82 engine_.seed(rd());
83 }
84
92 void seed(unsigned int s) { engine_.seed(s); }
93
103 int randint(int a, int b)
104 {
105 if (a > b) { // Python的randint行为/Python's randint behavior
106 std::swap(a, b);
107 }
108 std::uniform_int_distribution<int> dist(a, b);
109 return dist(engine_);
110 }
111
122 template<typename T>
123 T random_int(T a, T b)
124 {
125 static_assert(
126 std::is_integral_v<T>,
127 "random_int<T>(T,T) 仅支持整数类型/only supports integral types");
128 if (a > b) { // Python的randint行为/Python's randint behavior
129 std::swap(a, b);
130 }
131 std::uniform_int_distribution<T> dist(a, b);
132 return dist(engine_);
133 }
134
146 template<typename T>
147 T random_float(T a, T b)
148 {
149 static_assert(std::is_floating_point_v<T>,
150 "random_float<T>(T,T) 仅支持浮点类型/only supports floating "
151 "point types");
152 std::uniform_real_distribution<T> dist(a, b);
153 return dist(engine_);
154 }
155
167 template<typename T>
168 T random(T a, T b)
169 {
170 if constexpr (std::is_integral_v<T>) {
171 return random_int(a, b);
172 } else if constexpr (std::is_floating_point_v<T>) {
173 return random_float(a, b);
174 } else {
175 static_assert(std::is_integral_v<T> || std::is_floating_point_v<T>,
176 "random<T>(T,T) 仅支持整数和浮点类型/only supports "
177 "integral and floating point types");
178 return T {}; // 这行代码永远不会执行,只是为了避免编译错误/This line will
179 // never execute, just to avoid compile error
180 }
181 }
182
193 template<typename T>
195 {
196 if constexpr (std::is_floating_point_v<T>) {
197 return random_float<T>(0, 1);
198 } else if constexpr (std::is_integral_v<T>) {
199 return random_int<T>(0, std::numeric_limits<T>::max());
200 } else {
201 static_assert(std::is_floating_point_v<T> || std::is_integral_v<T>,
202 "random<T>() 仅支持浮点和整数类型/only supports floating "
203 "point and integral types");
204 return T {}; // 这行代码永远不会执行,只是为了避免编译错误/This line will
205 // never execute, just to avoid compile error
206 }
207 }
208
220 template<typename T>
221 T uniform(T a, T b)
222 {
223 std::uniform_real_distribution<T> dist(a, b);
224 return dist(engine_);
225 }
226
238 template<typename T>
239 T gauss(T mu, T sigma)
240 {
241 static_assert(
242 std::is_floating_point_v<T>,
243 "gauss<T>(T,T) 仅支持浮点类型/only supports floating point types");
244 std::normal_distribution<T> dist(mu, sigma);
245 return dist(engine_);
246 }
247
259 template<typename T>
260 T choice(const std::vector<T>& vec)
261 {
262 if (vec.empty()) {
263 throw std::out_of_range(
264 "无法从空vector中选择/Cannot choose from an empty vector");
265 }
266 // randint是闭区间[a, b],vector索引是[0, size-1]/randint is inclusive [a,
267 // b], vector index is [0, size-1]
268 return vec[randint(0, static_cast<int>(vec.size()) - 1)];
269 }
270
283 template<typename TContainer>
284 typename TContainer::value_type choice_general(const TContainer& container)
285 {
286 static_assert(toolbox::traits::is_iterable_v<TContainer>,
287 "choice_general<TContainer> 仅支持可迭代容器/only supports "
288 "iterable containers");
289 if (container.empty()) {
290 throw std::out_of_range(
291 "无法从空容器中选择/Cannot choose from an empty container");
292 }
293 std::uniform_int_distribution<size_t> dist(0, container.size() - 1);
294 auto it = container.begin();
295 std::advance(it, dist(engine_));
296 return *it;
297 }
298
308 template<typename TContainer>
309 void shuffle(TContainer& container)
310 {
311 std::shuffle(container.begin(), container.end(), engine_);
312 }
313
326 template<typename TContainer>
327 TContainer sample(const TContainer& population, size_t k)
328 {
329 if (k > population.size()) {
330 throw std::out_of_range(
331 "k不能大于容器大小/k cannot be greater than population size");
332 }
333 TContainer result;
334#if __cplusplus >= 201703L
335 std::sample(population.begin(),
336 population.end(),
337 std::back_inserter(result),
338 k,
339 engine_);
340#else
341 TContainer shuffled_population = population;
342 this->shuffle(
343 shuffled_population); // 使用自身的shuffle方法/Use own shuffle method
344 std::copy_n(shuffled_population.begin(), k, std::back_inserter(result));
345#endif
346 return result;
347 }
348
363 template<typename TContainer>
364 TContainer generate(std::size_t n,
365 typename TContainer::value_type min,
366 typename TContainer::value_type max)
367 {
368 TContainer result;
369 result.reserve(n);
370 for (std::size_t i = 0; i < n; ++i) {
371 result.push_back(random(min, max));
372 }
373 return result;
374 }
375
376private:
380 std::mt19937 engine_;
381};
382
392inline int randint(int a, int b)
393{
394 return random_t::instance().randint(a, b);
395}
396
408template<typename T>
409inline T random(T a, T b)
410{
411 return random_t::instance().random(a, b);
412}
413
423template<typename T>
424inline T random()
425{
426 if constexpr (std::is_floating_point_v<T>) {
427 return random_t::instance().random<T>(0, 1);
428 } else if constexpr (std::is_integral_v<T>) {
429 return random_t::instance().random<T>(0, std::numeric_limits<T>::max());
430 } else {
431 static_assert(std::is_floating_point_v<T> || std::is_integral_v<T>,
432 "random<T>() 仅支持浮点和整数类型/only supports floating "
433 "point and integral types");
434 return T {}; // 这行代码永远不会执行,只是为了避免编译错误/This line will
435 // never execute, just to avoid compile error
436 }
437}
438
450template<typename T>
451inline T uniform(T a, T b)
452{
453 return random_t::instance().uniform(a, b);
454}
455
467template<typename T>
468inline T gauss(T mu, T sigma)
469{
470 return random_t::instance().gauss(mu, sigma);
471}
472
483template<typename T>
484inline T choice(const std::vector<T>& vec)
485{
486 return random_t::instance().choice(vec);
487}
488
500template<typename T>
501inline std::vector<T> choice_n(const std::vector<T>& vec, size_t n)
502{
503 return random_t::instance().sample(vec, n);
504}
505
517template<typename T>
518inline std::vector<T> sample(const std::vector<T>& population, size_t k)
519{
520 return random_t::instance().sample(population, k);
521}
522
533template<typename TContainer>
534inline typename TContainer::value_type choice(const TContainer& container)
535{
536 static_assert(
537 toolbox::traits::is_iterable_v<TContainer>,
538 "choice<TContainer> 仅支持可迭代容器/only supports iterable containers");
539 return random_t::instance().choice_general(container);
540}
541
554template<typename TContainer>
555inline TContainer choice_n(const TContainer& container, size_t n)
556{
557 static_assert(toolbox::traits::is_iterable_v<TContainer>,
558 "choice_n<TContainer> 仅支持可迭代容器/only supports iterable "
559 "containers");
560 return random_t::instance().sample(container, n);
561}
562
575template<typename TContainer>
576inline TContainer sample(const TContainer& container, size_t n)
577{
578 static_assert(
579 toolbox::traits::is_iterable_v<TContainer>,
580 "sample<TContainer> 仅支持可迭代容器/only supports iterable containers");
581 return random_t::instance().sample(container, n);
582}
583
593template<typename TContainer>
594inline void shuffle(TContainer& container)
595{
596 random_t::instance().shuffle(container);
597}
598
613template<typename TContainer>
614inline TContainer generate(std::size_t n,
615 typename TContainer::value_type min,
616 typename TContainer::value_type max)
617{
618 return random_t::instance().generate<TContainer>(n, min, max);
619}
620
621} // namespace toolbox::utils
随机数工具类/Random number utility class
Definition random.hpp:32
int randint(int a, int b)
生成[a, b]范围内的随机整数/Generate random integer in [a, b]
Definition random.hpp:103
T choice(const std::vector< T > &vec)
从vector中随机选择一个元素/Randomly choose one element from vector
Definition random.hpp:260
TContainer generate(std::size_t n, typename TContainer::value_type min, typename TContainer::value_type max)
生成n个随机数/Generate n random numbers
Definition random.hpp:364
T gauss(T mu, T sigma)
生成高斯分布(正态分布)随机数/Generate Gaussian (normal) distributed random number
Definition random.hpp:239
T random_int(T a, T b)
生成指定整数类型的随机数/Generate random integer of given type
Definition random.hpp:123
void seed(unsigned int s)
使用指定种子设置/Reseed with specific value
Definition random.hpp:92
T random()
无参数版本的随机数生成函数/Random number generator without parameters
Definition random.hpp:194
void shuffle(TContainer &container)
随机打乱容器/Shuffle the container randomly
Definition random.hpp:309
TContainer sample(const TContainer &population, size_t k)
从容器中随机采样k个元素/Randomly sample k elements from container
Definition random.hpp:327
random_t(unsigned int seed_val)
使用指定种子初始化/Constructor, seeds with a specific value
Definition random.hpp:55
random_t()
构造函数,使用随机设备初始化种子/Constructor, seeds with a random_device by default
Definition random.hpp:42
void seed()
重新使用随机设备设置种子/Reseed with random_device
Definition random.hpp:79
T uniform(T a, T b)
生成[a, b]范围内的均匀分布浮点数/Generate uniform random float in [a, b]
Definition random.hpp:221
T random(T a, T b)
通用随机数生成函数/General random number generator
Definition random.hpp:168
TContainer::value_type choice_general(const TContainer &container)
通用容器的随机选择/General random choice for containers supporting iterators and size()
Definition random.hpp:284
T random_float(T a, T b)
生成指定浮点类型的随机数/Generate random floating point number of given type
Definition random.hpp:147
static random_t & instance()
获取单例实例/Get singleton instance
Definition random.hpp:67
< 用于 std::out_of_range/For std::out_of_range
Definition click.hpp:11
int randint(int a, int b)
生成[a, b]范围内的随机整数/Generate random integer in [a, b]
Definition random.hpp:392
T choice(const std::vector< T > &vec)
从vector中随机选择一个元素/Randomly choose one element from vector
Definition random.hpp:484
TContainer generate(std::size_t n, typename TContainer::value_type min, typename TContainer::value_type max)
生成n个随机数/Generate n random numbers
Definition random.hpp:614
T gauss(T mu, T sigma)
生成高斯分布(正态分布)随机数/Generate Gaussian (normal) distributed random number
Definition random.hpp:468
std::vector< T > choice_n(const std::vector< T > &vec, size_t n)
从vector中随机选择n个元素/Randomly choose n elements from vector
Definition random.hpp:501
T uniform(T a, T b)
生成[a, b]范围内的均匀分布浮点数/Generate uniform random float in [a, b]
Definition random.hpp:451
T random()
无参数版本的随机数生成函数/Random number generator without parameters
Definition random.hpp:424
std::vector< T > sample(const std::vector< T > &population, size_t k)
从vector中随机采样k个元素/Randomly sample k elements from vector
Definition random.hpp:518
void shuffle(TContainer &container)
随机打乱容器/Shuffle the container randomly
Definition random.hpp:594
类型特征工具集合/Type traits utilities collection