Console Library 8.0.0
A header-only library that makes C++ simple
Loading...
Searching...
No Matches
random.h
Go to the documentation of this file.
1
8
9/*
10Copyright (c) 2026 MrXie1109
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files (the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions:
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29*/
30
31#pragma once
32#include <chrono>
33#include <cstdint>
34#include <initializer_list>
35#include <numeric>
36#include <random>
37#include <utility>
38
39#include "../core/csexc.h"
40#include "../core/sfinae.h"
41
42namespace console {
48
55 inline std::mt19937 &thread_rng() {
56 thread_local std::mt19937 gen(std::chrono::high_resolution_clock::now()
57 .time_since_epoch()
58 .count());
59 return gen;
60 }
61
67 template <class T>
68 inline void seed(T seed) {
69 thread_rng().seed(seed);
70 }
71
80 template <class T = int>
81 T randint(T min = 0, T max = 32767, std::mt19937 &gen = thread_rng()) {
82 return std::uniform_int_distribution<T>(min, max)(gen);
83 }
84
93 template <class T = double>
94 T uniform(T min = 0.0, T max = 1.0, std::mt19937 &gen = thread_rng()) {
95 return std::uniform_real_distribution<T>(min, max)(gen);
96 }
97
104 inline bool randbool(double p = 0.5, std::mt19937 &gen = thread_rng()) {
105 return std::bernoulli_distribution(p)(gen);
106 }
107
117 template <class C>
118 auto
119 choice(C &c, std::mt19937 &gen = thread_rng()) -> decltype(*std::begin(c)) {
120 if (std::begin(c) == std::end(c))
121 throw ContainerError("Empty container");
122 return *std::next(std::begin(c), randint<size_t>(0, c.size() - 1, gen));
123 }
124
134 template <class C>
135 auto choice(const C &c, std::mt19937 &gen = thread_rng())
136 -> decltype(*std::begin(c)) {
137 if (std::begin(c) == std::end(c))
138 throw ContainerError("Empty container");
139 return *std::next(std::begin(c), randint<size_t>(0, c.size() - 1, gen));
140 }
141
151 template <class C>
152 auto choice(C &&c, std::mt19937 &gen = thread_rng())
153 -> decltype(*std::begin(c)) {
154 if (std::begin(c) == std::end(c))
155 throw ContainerError("Empty container");
156 return *std::next(std::begin(c), randint<size_t>(0, c.size() - 1, gen));
157 }
158
167 template <class T>
168 T choice(std::initializer_list<T> init, std::mt19937 &gen = thread_rng()) {
170 }
171
179 template <class C>
180 void shuffle(C &&c, std::mt19937 &gen = thread_rng()) {
181 if (std::begin(c) == std::end(c)) return;
182 for (size_t i = c.size() - 1; i > 0; i--) {
183 auto j = randint<size_t>(0, i, gen);
184 std::swap(
185 *std::next(std::begin(c), i), *std::next(std::begin(c), j));
186 }
187 }
188
198 template <class T = double>
199 std::vector<T> rnorm(
200 size_t n, T mean = 0.0, T sd = 1.0, std::mt19937 &gen = thread_rng()) {
201 std::vector<T> vec(n);
202 std::normal_distribution<T> dist(mean, sd);
203 for (T &t : vec) t = dist(gen);
204 return vec;
205 }
206
216 template <class T = double>
217 std::vector<T> runif(
218 size_t n, T min = 0.0, T max = 1.0, std::mt19937 &gen = thread_rng()) {
219 std::vector<T> vec(n);
221 for (T &t : vec) t = dist(gen);
222 return vec;
223 }
224
234 template <class T = int>
235 std::vector<T>
236 rbinom(size_t n, T size, double prob, std::mt19937 &gen = thread_rng()) {
237 std::vector<T> vec(n);
238 std::binomial_distribution<T> dist(size, prob);
239 for (T &t : vec) t = dist(gen);
240 return vec;
241 }
242
251 template <class T = int>
252 std::vector<T>
253 rpois(size_t n, double lambda, std::mt19937 &gen = thread_rng()) {
254 std::vector<T> vec(n);
255 std::poisson_distribution<T> dist(lambda);
256 for (T &t : vec) t = dist(gen);
257 return vec;
258 }
259
268 template <class T = double>
269 std::vector<T>
270 rexp(size_t n, T rate = 1.0, std::mt19937 &gen = thread_rng()) {
271 std::vector<T> vec(n);
272 std::exponential_distribution<T> dist(rate);
273 for (T &t : vec) t = dist(gen);
274 return vec;
275 }
276
287 template <class T = double>
288 std::vector<T>
289 rgamma(size_t n, T shape, T rate = 1.0, std::mt19937 &gen = thread_rng()) {
290 std::vector<T> vec(n);
291 std::gamma_distribution<T> dist(shape, 1.0 / rate);
292 for (T &t : vec) t = dist(gen);
293 return vec;
294 }
295
307
308 template <class T = double>
309 std::vector<T>
310 rbeta(size_t n, T shape1, T shape2, std::mt19937 &gen = thread_rng()) {
311 std::vector<T> vec(n);
312 std::gamma_distribution<T> dist_a(shape1, 1.0);
313 std::gamma_distribution<T> dist_b(shape2, 1.0);
314 for (T &t : vec) {
315 T x = dist_a(gen);
316 T y = dist_b(gen);
317 t = x / (x + y);
318 }
319 return vec;
320 }
321
331 template <class T = double>
332 std::vector<T> rchisq(size_t n, T df, std::mt19937 &gen = thread_rng()) {
333 return rgamma(n, df / 2.0, 0.5, gen);
334 }
335
344 template <class T = double>
345 std::vector<T> rt(size_t n, T df, std::mt19937 &gen = thread_rng()) {
346 std::vector<T> vec(n);
347 std::student_t_distribution<T> dist(df);
348 for (T &t : vec) t = dist(gen);
349 return vec;
350 }
351
361 template <class T = double>
362 std::vector<T>
363 rf(size_t n, T df1, T df2, std::mt19937 &gen = thread_rng()) {
364 std::vector<T> vec(n);
365 std::fisher_f_distribution<T> dist(df1, df2);
366 for (T &t : vec) t = dist(gen);
367 return vec;
368 }
369
379 template <class T = double>
380 std::vector<T> rlnorm(size_t n,
381 T meanlog = 0.0,
382 T sdlog = 1.0,
383 std::mt19937 &gen = thread_rng()) {
384 std::vector<T> vec(n);
385 std::lognormal_distribution<T> dist(meanlog, sdlog);
386 for (T &t : vec) t = dist(gen);
387 return vec;
388 }
389
399 template <class T = double>
400 std::vector<T> rweibull(
401 size_t n, T shape, T scale = 1.0, std::mt19937 &gen = thread_rng()) {
402 std::vector<T> vec(n);
403 std::weibull_distribution<T> dist(shape, scale);
404 for (T &t : vec) t = dist(gen);
405 return vec;
406 }
407
420 template <class C>
421 std::vector<typename C::value_type> sample(const C &c,
422 size_t size,
423 bool replace = false,
424 std::mt19937 &gen = thread_rng()) {
425 using value_type = typename C::value_type;
426 std::vector<value_type> result;
427 result.reserve(size);
428 auto it_begin = std::begin(c);
429 auto it_end = std::end(c);
430 size_t n = std::distance(it_begin, it_end);
431 if (n == 0) throw ContainerError("Cannot sample from empty container");
432 if (!replace && size > n)
433 throw ContainerError(
434 "Sample size exceeds container size when replace=false");
435 if (replace)
436 for (size_t i = 0; i < size; ++i) {
437 result.push_back(*std::next(it_begin,
438 std::uniform_int_distribution<size_t>(0, n - 1)(gen)));
439 }
440 else {
441 std::vector<size_t> indices(n);
442 std::iota(indices.begin(), indices.end(), 0);
443 shuffle(indices, gen);
444 for (size_t i = 0; i < size; ++i)
445 result.push_back(*std::next(it_begin, indices[i]));
446 }
447 return result;
448 }
449
462 template <class T>
463 std::vector<T> sample(std::initializer_list<T> init,
464 size_t size,
465 bool replace = false,
466 std::mt19937 &gen = thread_rng()) {
467 return sample<std::initializer_list<T>>(init, size, replace, gen);
468 }
469 // end of random group
471}
ContainerError(const std::string &msg)
构造 ContainerError。
Definition csexc.h:140
定义 console 库使用的自定义异常类层次结构。
double mean(const MultiArray< T, Dims... > &arr)
计算 MultiArray 中所有元素的算术平均值。
Definition matools.h:66
std::vector< T > rt(size_t n, T df, std::mt19937 &gen=thread_rng())
生成 n 个服从 t 分布(Student's t-distribution)的随机数。
Definition random.h:345
T randint(T min=0, T max=32767, std::mt19937 &gen=thread_rng())
生成一个指定范围内的随机整数(均匀分布)。
Definition random.h:81
std::vector< T > rweibull(size_t n, T shape, T scale=1.0, std::mt19937 &gen=thread_rng())
生成 n 个服从韦布尔分布(Weibull Distribution)的随机数。
Definition random.h:400
auto choice(C &c, std::mt19937 &gen=thread_rng()) -> decltype(*std::begin(c))
从容器中随机选择一个元素(左值版本,返回引用)。
Definition random.h:119
std::vector< T > runif(size_t n, T min=0.0, T max=1.0, std::mt19937 &gen=thread_rng())
生成 n 个服从均匀分布(Uniform Distribution)的随机数。
Definition random.h:217
std::vector< typename C::value_type > sample(const C &c, size_t size, bool replace=false, std::mt19937 &gen=thread_rng())
从容器中随机抽取指定数量的元素(有放回或无放回)。
Definition random.h:421
bool randbool(double p=0.5, std::mt19937 &gen=thread_rng())
生成一个服从伯努利分布(Bernoulli Distribution)的随机布尔值。
Definition random.h:104
std::mt19937 & thread_rng()
获取一个全局的、以当前时间戳为种子的 Mersenne Twister 随机数引擎。
Definition random.h:55
std::vector< T > rnorm(size_t n, T mean=0.0, T sd=1.0, std::mt19937 &gen=thread_rng())
生成 n 个服从正态分布(Normal Distribution)的随机数。
Definition random.h:199
std::vector< T > rpois(size_t n, double lambda, std::mt19937 &gen=thread_rng())
生成 n 个服从泊松分布(Poisson Distribution)的随机数。
Definition random.h:253
std::vector< T > rexp(size_t n, T rate=1.0, std::mt19937 &gen=thread_rng())
生成 n 个服从指数分布(Exponential Distribution)的随机数。
Definition random.h:270
std::vector< T > rbinom(size_t n, T size, double prob, std::mt19937 &gen=thread_rng())
生成 n 个服从二项分布(Binomial Distribution)的随机数。
Definition random.h:236
std::vector< T > rgamma(size_t n, T shape, T rate=1.0, std::mt19937 &gen=thread_rng())
生成 n 个服从伽马分布(Gamma Distribution)的随机数。
Definition random.h:289
std::vector< T > rlnorm(size_t n, T meanlog=0.0, T sdlog=1.0, std::mt19937 &gen=thread_rng())
生成 n 个服从对数正态分布(Lognormal Distribution)的随机数。
Definition random.h:380
std::vector< T > rchisq(size_t n, T df, std::mt19937 &gen=thread_rng())
生成 n 个服从卡方分布(Chi-squared Distribution)的随机数。
Definition random.h:332
void seed(T seed)
修改 thread_rng 提供的随机数引擎的种子。
Definition random.h:68
T uniform(T min=0.0, T max=1.0, std::mt19937 &gen=thread_rng())
生成一个指定范围内的随机浮点数(均匀分布)。
Definition random.h:94
void shuffle(C &&c, std::mt19937 &gen=thread_rng())
随机打乱容器中元素的顺序(Fisher-Yates 洗牌算法)。
Definition random.h:180
std::vector< T > rf(size_t n, T df1, T df2, std::mt19937 &gen=thread_rng())
生成 n 个服从 F 分布(Fisher–Snedecor F-distribution)的随机数。
Definition random.h:363
std::vector< T > rbeta(size_t n, T shape1, T shape2, std::mt19937 &gen=thread_rng())
生成 n 个服从贝塔分布(Beta Distribution)的随机数。
Definition random.h:310
typename uniform_distribution_impl< T >::type uniform_distribution_t
取得对印类型所对应的均匀分布。
Definition sfinae.h:328
Definition gen.h:237
本库所有组件所在的顶层命名空间。
T min(const MultiArray< T, Dims... > &a)
求最小值。
Definition multiarray.h:1676
T max(const MultiArray< T, Dims... > &a)
求最大值。
Definition multiarray.h:1685
@ T
Definition kb.h:99
提供编译期类型特征检测(SFINAE 工具), 用于判断容器、可调用对象、迭代器、下标访问、字符串、可打印类型、字符类型等。