【问题标题】:How to generate uniformly distributed random reals for custom types without reinventing the wheel?如何在不重新发明轮子的情况下为自定义类型生成均匀分布的随机实数?
【发布时间】:2017-01-21 09:09:29
【问题描述】:

我打算将std::uniform_real_distribution 与一些非内置的类浮点类型一起使用,例如half_float::halfboost::multiprecision::float128。但我得到的是

/opt/gcc-5.2/include/c++/5.2.0/bits/random.h:1868:7:错误:静态断言失败:模板参数不是浮点类型

来自 g++ 5.2。这是示例程序(使用g++ -std=c++11 -fext-numeric-literals test.cpp -o test 编译):

#include <random>
#include <boost/multiprecision/float128.hpp>
#include <half.hpp>

template<typename Float>
void test()
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<Float> rnd(Float(1),Float(10));
}

int main()
{
    test<float>();
    test<double>();
    test<long double>();
    test<boost::multiprecision::float128>(); // doesn't compile
    test<half_float::half>(); // doesn't compile
}

那么,应该如何为此类自定义类型生成均匀分布的随机实数?有没有办法不用重新发明轮子?

【问题讨论】:

  • 如何定义一个接受 1 到 n 个浮点数并返回您最喜欢的浮点类型的函数?然后将随机浮点数作为输入,也许作为默认参数。
  • @lorro 你的意思是一个函数将浮点类型从内置类型转换为我需要的类型吗?但这不会使分布保持一致。
  • 我的意思是数学意义上的“函数”:自定义浮点数和 N 个标准浮点数之间的一对一映射(反之亦然,如果你的浮点数小于标准浮点数) .用整数更容易解释:伪代码:int64_t getint64(int32_t a, int32_t b) { return int64_t(a) &lt;&lt; 32 + b; }。可以为所有类型创建这样的函数(也许通过忽略最重要的位中的一些位)。
  • @lorro 为浮点数定义这样一个函数的棘手部分是确保对于均匀分布在 [a,b) intersected with the set of values of input type 上的 N 个参数,它会给出均匀分布在 [a,b) intersected with the set of values of output types 上的结果。

标签: c++ random floating-point


【解决方案1】:

here可以看出,uniform_real_distribution定义为:

template< class RealType = double >
class uniform_real_distribution;

RealType 在哪里:

生成器生成的结果类型。如果这不是 float、double 或 long double 之一,则效果未定义。

您的编译器似乎明确禁止使用自定义类型作为处理(让我说)不接受的类型的解决方案。因此我会说你没有机会让它工作。

【讨论】:

  • 好的,但实际的问题是如果有的话,有什么好的替代方案,即我可以使用的东西来代替我自己的均匀分布实现。
  • @Ruslan 您可以使用floatdoublelong double 作为类型。就这样。或者您正在寻找uniform_real_distribution 的替代品?
  • 是的,我正在寻找一种适用于其他浮点类型的替代机制。
  • @Ruslan 它们与内置类型不同。使用标准模板库可以做的最好的事情是编写一个在内部使用uniform_real_distributionfloats 的生成器,并返回你想要的类型。无论如何,转换可能会缩小使用uniform_real_distribution 的好处。
【解决方案2】:

标准中定义的与RealType 类型一起使用的标准随机数工具必须将floatdoublelong double 作为类型模板参数,如26.5.1.1.d 中所示:

在整个 26.5 小节中,实例化模板的效果:

<...>

d) 具有名为 RealType 的模板类型参数是未定义的,除非相应的模板参数是 cv-unqualified 并且是 floatdoublelong double 之一。

一种解决方案是将std::uniform_real_distribution 替换为boost::random::uniform_real_distribution。后者确实接受非内置浮点类型。这是一个具有合理类型的示例*

#include <random>
#include <boost/random/uniform_real_distribution.hpp>
#include <boost/multiprecision/float128.hpp>

template<typename Float>
void test()
{
    std::random_device rd;
    std::mt19937 mt(rd());
    boost::random::uniform_real_distribution<Float> rnd(Float(1),Float(10));
}

int main()
{
    test<float>();
    test<double>();
    test<long double>();
    test<boost::multiprecision::float128>();
}

*half_float::half 不起作用,因为它乘以一个常数会导致 float,而 half_float::half(float) 构造函数是显式的,并且 Boost 的实现不会调用它明确

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-16
    • 2014-08-16
    • 2015-08-14
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 1970-01-01
    • 2016-05-09
    相关资源
    最近更新 更多