如何枚举在min和max之间的所有浮点值

How to enumerate all floating point values in between min and max

本文关键字:之间 max 何枚举 枚举 min      更新时间:2023-10-16

为一个有效的随机数生成器唯一的浮点值我想知道更多关于浮点值。我将把我的问题分成两部分。

  1. 我如何找出有多少浮动在最小和最大之间(包括两者)?

我正在寻找方法的实现:

size_t numOfFloats(const float min, const float max);

考虑给定数据类型的最大精度的所有可能的浮点值。

  • 我如何枚举最小和最大之间的所有可能的浮动值(包括两者)?
  • 我正在寻找方法的实现:

    vector<float> enumAllFloats(const float min, const float max);
    

    返回的vector的大小应该始终等于第一个问题的方法的返回值。

    您可以使用nextafterf来枚举所有可表示的浮点数:

    vector<float> enumAllFloats(const float tmin, const float tmax) {
      vector<float> res;
      for (float x = tmin; x < tmax; x = nextafterf(x, tmax))
        res.push_back(x);
      res.push_back(tmax);
      return res;
    }
    

    可以使用浮点数的ieee754表示将它们映射为int。然后,用整型数计算一下。

    注意下面的代码不适合负数,并且不考虑特殊浮点值(NaN,无穷大…)

    size_t numOfFloats(const float min, const float max){
        // assert 0 <= min <= max
        // assert sizeof(float) == sizeof(int32_t)
        const int32_t min_i = *reinterpret_cast<const int32_t*>(&min);
        const int32_t max_i = *reinterpret_cast<const int32_t*>(&max);
        return max_i-min_i+1;
    }
    

    同样,当你知道与int的映射关系时,你可以很容易地列出它们:

    void print_successive_floats(const float min, const float max){
        const int32_t min_i = *reinterpret_cast<const int32_t*>(&min);
        const int32_t max_i = *reinterpret_cast<const int32_t*>(&max);
        for(int32_t i = min_i; i<=max_i; ++i){
            float f = *reinterpret_cast<float*>(&i);
            std::cout << f << std::endl;
        }
    }
    

    为了完整,为了匹配你的API:

    vector<float> enumAllFloats(const float min, const float max){
        vector<float> out;
        out.reserve(numOfFloats(min, max));
        const int32_t min_i = *reinterpret_cast<const int32_t*>(&min);
        const int32_t max_i = *reinterpret_cast<const int32_t*>(&max);
        for(int32_t i = min_i; i<=max_i; ++i){
            float f = *reinterpret_cast<float*>(&i);
            out.push_back(f);
        }
        return out;
    }
    

    小心巨大的向量=)

    我假设您的目标架构使用浮点数的标准IEEE表示(IEEE754,如果我没有弄错的话)。

    这种表示法的一个性质是,具有相同符号的相邻浮点数具有相邻表示法,也就是说,如果将某些float的(32位)二进制表示法视为(32位)int,则具有相同符号的相邻浮点数对应的int s相差正好1。

    所以如果你的minmax都是相同的符号,那么你可以把它们转换成int s,然后做一个简单的循环。

    类似于(从这里改编的代码,我也建议作为更多信息的来源):

    /* See
    https://randomascii.wordpress.com/2012/01/11/tricks-with-the-floating-point-format/
    for the potential portability problems with the union and bit-fields below.
    */
    union Float_t
    {
        int32_t i;
        float f;
    };
    vector<float> enumAllFloats(const float min, const float max) {
        std::vector<float> result;
        Float_t fl;
        fl.f = min;
        result.push_back(fl.f);
        for (; fl.f <= max; fl.i++)
            result.push_back(fl.f);
        return result;
    }
    

    如果minmax可以有不同的符号,则必须分别在范围的正负部分进行循环。此外,如果minmax都是负的,也许您必须将它们交换为上面的代码。


    但是,如果您确实想将其用于RNG,请小心,因为这些浮点数在[min, max]范围内不会均匀分布。