如何将浮点数初始化为其最大值/最小值?


100

如何对浮点数或双精度数的绝对最大值或最小值进行硬编码?我想通过简单地遍历并捕获最大的数组来搜索数组的最大值/最小值。

浮点数也有正负无穷大,我应该改用它们吗?如果是这样,我该如何在代码中表示呢?

Answers:


151

您可以使用std::numeric_limits其中定义的值<limits>来查找类型的最小值或最大值(只要该类型存在特殊化)。您还可以使用它来检索无穷大(并-在前面放置负无穷大)。

#include <limits>

//...

std::numeric_limits<float>::max();
std::numeric_limits<float>::min();
std::numeric_limits<float>::infinity();

如注释中所述,min()返回可能的最低正值。换句话说,可以表示最接近0的正值。最低可能值是最大可能值的负数。

当然,std::max_element还有和min_element函数(在中定义<algorithm>)可能是查找数组中最大值或最小值的更好选择。


我到底该如何使用呢?我需要包括什么?我认为我以前没有使用过这种东西。
Faken 2010年

嗯...最大元素功能将非常有用...这是当您独自学习而不是正式学习编码时发生的情况。您最终将轮子重新发明了50次。这就像我上次了解ceil()一样。谢谢。
Faken

18
@Yacoby,您可能想弄清楚numeric_limits <float> :: min()并不意味着最大的负值,而是意味着最小的正值。
MSN 2010年

13
@killogre:添加了C ++ 11 numeric_limits<T>::lowest(),它返回用于解决该问题的类型的最低(负)值。
2013年

3
std::numeric_limits<float>::min()没有得到能够表示的最小正值; 它给出最小的常规单精度浮点数。在零和该数字之间也存在非正规数。特别是,std::numeric_limits<float>::min()给出1.17549e-38最小的可表示的次正规浮点为nextafterf(0.0f, 1.0f) == 1.4013e-45f
nibot

45

您可以将-FLT_MAX(或-DBL_MAX)表示为最大负数,将FLT_MAX(或DBL_MAX)表示为正数。这为您提供了可能的浮点(或双精度)值范围。

您可能不想使用FLT_MIN; 它对应于可以用浮点数表示的最小量级正数,而不是可以用浮点数表示的最大负数。

FLT_MIN并且FLT_MAX对应于std::numeric_limits<float>::min()std::numeric_limits<float>::max()


我想我会实际使用这个版本,它更容易记住并且给我带来更多景象。我可以使用十六进制初始化整数。虽然,最佳答案仍然存在,因为答案也向我介绍了一些新的非常有用的功能。
Faken

2
“ [ FLT_MIN]对应可以用浮点数表示的最小正数”- 这是不正确的。这是最小的标准数。也有不正常的数字。
nibot

您想要FLT_TRUE_MIN实际最小的浮动,对应于std::numeric_limits<float>::denorm_min()
Chris Dodd

17

真正没有必要初始化为最小/最大来找到数组中的最小/最大:

double largest = smallest = array[0];
for (int i=1; i<array_size; i++) {
    if (array[i] < smallest)
        smallest = array[i];
    if (array[i] > largest0
        largest= array[i];
}

或者,如果您不止一次这样做:

#include <utility>

template <class iter>
std::pair<typename iter::value_type, typename iter::value_type> find_extrema(iter begin, iter end) {
    std::pair<typename iter::value_type, typename iter::value_type> ret;
    ret.first = ret.second = *begin;
    while (++begin != end) {
        if (*begin < ret.first)
           ret.first = *begin;
        if (*begin > ret.second)
           ret.second = *begin;
   }
   return ret;
}

提供示例代码的缺点-我看到其他人已经提出了相同的想法。

请注意,尽管标准具有min_element和max_element,但使用它们将需要对数据进行两次扫描,如果数组很大,则可能会出现问题。最近的标准通过添加来解决此问题std::minmax_element,该功能与find_extrema上面的功能相同(在一次遍历中找到集合中的最小和最大元素)。

编辑:解决在无符号数组中查找最小的非零值的问题:观察到无符号值达到极限时会“环绕”。为了找到最小的非零值,我们可以从每个值中减去一个进行比较。任何零值都将“包装”为该类型的最大可能值,但其他值之间的关系将保留。完成后,我们显然会将一加到找到的值上。

unsigned int min_nonzero(std::vector<unsigned int> const &values) { 
    if (vector.size() == 0)
        return 0;
    unsigned int temp = values[0]-1;
    for (int i=1; i<values.size(); i++)
        if (values[i]-1 < temp)
            temp = values[i]-1;
    return temp+1;
}

请注意,这仍然使用第一个元素作为初始值,但是我们仍然不需要任何“特殊情况”代码-因为它将环绕到最大可能值,所以任何非零值都将比较小。结果将是最小的非零值,或者仅当向量不包含非零值时才为0。


但是您从我这里得到+1!
Dan Diplo

1
我初始化为最大分钟数,因为有时我想要最小的非零值(例如,在无符号整数的情况下,我的数据倾向于有很多无趣的零)。对我来说,初始化它似乎很有意义,而不是执行额外的检查以确保第一个元素不为零。
Faken

@Faken:即使如此,您仍然可以定义一个比较函数,将零视为最大可能值,因此您仍然可以使用std::min_elementbool less_ignoring_zero(unsigned a, unsigned b) { if (a == 0) return false; if (b == 0) return true; return a < b; }
UncleBens 2010年

2
@Jerry:C ++ 0x将添加minmax_element来解决您提到的问题。(但那样就不可能忽略零...)
UncleBens 2010年

1
如果在初始化时第一个元素不可用怎么办?在线处理中
经常

5

要手动查找数组的最小值,您无需知道float的最小值:

float myFloats[];
...
float minimum = myFloats[0];
for (int i = 0; i < myFloatsSize; ++i)
{
  if (myFloats[i] < minimum)
  {
    minimum = myFloats[i];
  }
}

和类似代码的最大值。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.