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

时间:2015-07-17 10:27:12

标签: c++ floating-point

对于唯一浮点值的有效随机数生成器我想更多地了解浮点值。我将把问题分成两部分。

  1. 如何找出最小值和最大值(包括两者)之间有多少个浮点数?
  2. 我正在寻找该方法的实现:

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

    考虑到数据类型的最大精度,它会考虑所有可能的浮点值。

    1. 如何在min和max之间枚举所有可能的浮点值(包括两者)?
    2. 我正在寻找该方法的实现:

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

      返回的向量的大小应始终等于我第一个问题的方法的返回值。

      如果需要,允许使用C ++ 11.

3 个答案:

答案 0 :(得分:9)

您可以使用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;
}

答案 1 :(得分:4)

您可以使用浮点数的ieee754表示将它们映射到int。然后,用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;
}

此外,当您知道带有整数的映射时,可以轻松列出它们:

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;
}

谨防巨大的载体=)

答案 2 :(得分:3)

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

此表示的一个属性是相同符号的相邻浮点数具有相邻表示形式,即如果将某些float的(32位)二进制表示形式视为(32位){{ 1}},相同符号的相邻浮点数将使相应的int相差一个。

因此,如果您的intmin符号相同,那么您可以将它们转换为max,然后进行简单循环。

类似的东西(代码改编自here,我也建议作为更多信息的来源):

int

如果/* 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; } min有不同的符号,则必须分别在范围的正负部分循环。此外,如果两者都是否定的,您可能需要将maxmin换成上面的代码。

但是,如果您确实想将它用于RNG,请注意,因为这些浮动不会在max范围内均匀分布。