如何创建没有特定定义的随机分布?uniform_int_distribution是从其他类继承的吗?

How to create a random distribution with no specific definition? Is uniform_int_distribution inheriting from other class?

本文关键字:int uniform distribution 继承 其他 分布 随机 创建 何创建 定义      更新时间:2023-10-16

我想创建一段使用名为Number的代码,该类型可以是浮点数或任何整数(例如uint64_t(。我有一个变量dist,即应该用于生成随机数的分布,但在任何这些情况下都应该不同,所以我想做这样的事情:

constexpr bool number_is_floating = std::is_floating_point<Number>::value;
#if number_is_floating
std::uniform_real_distribution<Number> dist(1.0, 1000.0);
#else
std::uniform_int_distribution<Number> dist(1, 1000);
#endif

但这当然是行不通的,因为预处理器变量在常量number_is_floating之前被计算,所以这个表达式总是假的。我实际上尝试这样做:

Number getran() {
if constexpr (number_is_floating)
return std::uniform_real_distribution<Number>(1.0, 1000.0)(eng);
else
return std::uniform_int_distribution<Number>(1, 1000)(eng);
}

但这不起作用,因为我们正在尝试编译使用可能是也可能不是整数的类型(对于实际分布也是如此(初始化uniform_int_distribution的代码。

使此代码工作的最佳和最优雅的方法是什么,即使Number浮点数或不是浮点数?

但这不起作用,因为我们正在尝试编译以整数或可能不是整数的类型启动uniform_int_distribution的代码(对于实际分布也是如此(。

不,if constexpr在编译时计算,并且只编译其中一个分支,另一个被丢弃,例如编译。像这样的东西编译并按(可能(预期工作:

#include <random>
#include <iostream>
#include <type_traits>
template<typename TNumber>
TNumber getran() {
static std::default_random_engine eng; // Just to avoid undefined variables
if constexpr (std::is_floating_point<TNumber>::value) 
return std::uniform_real_distribution<TNumber>(1.0, 1000.0)(eng);
else
return std::uniform_int_distribution<TNumber>(1, 1000)(eng);
}
int main()
{   
std::cout << getran<float>() << ", "
<< getran<int>() << ", "
<< getran<double>() << ", "
<< getran<unsigned>();
}
Number getran_internal(std::integral_constant<bool, true> is_floating) {
return std::uniform_real_distribution<Number>(1.0, 1000.0)(eng);
}
Number getran_internal(std::integral_constant<bool, false> is_floating) {
return std::uniform_int_distribution<Number>(1, 1000)(eng);
}
Number getran() {
return getran_internal( std::integral_constant<bool, number_is_floating>{} );
}

一种方式,多种方式。

哪种方式是理想的,取决于您的编译器对各种 C++11 及以上功能的支持。 这个应该适用于任何 C++11 编译器。

我会声明一个模板函数,并在为每个特定类型实现它时使用相应的发行版。

typedef std::default_random_engine generator;
typedef float Number;
template <typename T>
T next_random_number(generator &g);
template<>
float next_random_number<float>(generator &g) {
std::uniform_real_distribution<float> dist(1.0, 1000.0);
return dist(g);
}
template<>
int next_random_number<int>(generator &g) {
std::uniform_int_distribution<int> dist(1, 1000);
return dist(g);
}
Number next(generator &g) {
return next_random_number<Number>(g);
}
int main() {
std::random_device r;
generator g(r());
for(int i = 0; i < 10; i++)
std::cout << next(g) << std::endl;
return 0;
}

希望我正确理解你的问题。