如何解决numeric_limits <t> :: min()的不一致定义?</t>

时间:2009-04-29 07:49:39

标签: c++ standard-library

numeric_limits traits应该是获取各种类型信息的一般方法,能够做到像

这样的事情
template<typename T>
T min(const std::vector<T>& vect)
{
    T val = std::numeric_limits<T>::min();

    for(int i=0 ; i<vect.size() ; i++)
        val = max(T, vect[i]);

    return val;
}

问题是(至少使用MS Visual Studio 2008)numeric_limits&lt; int&gt; :: min()返回最小的负数,而numeric_limits&lt; double&gt; :: min()返回最小的正数数字!

有谁知道这个设计背后的理性?是否有更好的(推荐?)方式使用numeric_limits?在我上面的特定函数中,我当然可以将T初始化为vect [0],但这不是我要找的答案..

另请参见(特定于浮点)讨论 here

7 个答案:

答案 0 :(得分:9)

您可以使用Boost库。库Numeric Conversions提供了一个名为bounds的类,可以一致地使用。

请参阅文档here

答案 1 :(得分:6)

这是一个旧线程,但有一个更新的答案:

C ++ 11向lowest()添加std::numeric_limits函数(See here

因此,您现在可以调用std::numeric_limits<double>::lowest()来获得可表示最低的负值。

答案 2 :(得分:4)

min()的行为并不奇怪,它会返回FLT_MINDBL_MININT_MIN(或它们各自的值),具体取决于您专注的类型。因此,您的问题应该是为FLT_MINDBL_MIN定义与INT_MIN不同的原因。

不幸的是,我不知道后一个问题的答案。

我怀疑它是出于实际目的而定义的。对于整数,您通常关注溢出/下溢,其中最小值和最大值变得有意义。

对于浮点数,存在一种不同类型的下溢,因为计算可能导致值大于零,但小于该浮点类型的最小可表示小数。知道最小的可表示浮点值可以让您解决问题。另见关于subnormal/denormal数字的维基百科文章。

答案 3 :(得分:1)

解决方法是

double val = -std::numeric_limits<double>::max();

当然,这并不能解释numerics_limits :: min()的奇怪行为,这可能是因为整数有不同的最小/最大边界(min = -2 ^ n,max = 2) ^ n-1)但不是双打。

答案 4 :(得分:1)

可以论证空矢量的最小值的定义。如果向量为空,则没有最小元素。

更喜欢使用std::min_element

int main()
{
    std::vector<int> v;
    std::generate_n(std::back_inserter(v), 1000, std::rand);

    std::vector<int>::iterator it  = std::min_element(v.begin(), v.end());
    if (it == v.end())
    {
        std::cout << "There is no smallest element" << std::endl;
    }
    else
    {
        std::cout << "The smallest element is " << *it << std::endl;
    }
}

答案 5 :(得分:1)

我不确定理由,但这是预期的行为。好吧,从某种意义上说,Josuttis(以及可能是标准)描述它的方式!

  

min():“Miniumum有限值(最小值   浮点的归一化值   具有非规范化的类型。“

最好我可以判断类型不是是否为整数(numeric_limits<>::is_integer)而非规范化(numeric_limits<>::has_denorm){{1} }将返回该类型的最小可表示值。否则它将返回最小的 - 这可能是负数。

要获得更一致的界面,请查看Boost numeric/conversion库。特别是bounds traits class。这是一个片段:

min()

您可能还会发现boost::integer library有用。它为C ++带来了一些C99的整数支持(如cout << "lowest float:" << boost::numeric::bounds<float>::lowest(); cout << "lowest int: " << boost::numeric::bounds<int>::lowest(); ),可以帮助您根据需要选择最合适的类型。一个例子:

int_least16_t

我经常发现,当我需要boost :: numeric / conversion或boost :: integer时,我需要它们。

答案 6 :(得分:1)

numeric_limits<int>::min返回最低负数,所有浮点数类型,当我尝试使用Sun CC&amp;时返回最小正数。克++

我想这是因为'最小'和'最小'意味着浮点数不同。虽然有点奇怪。

Sun CC和g ++都产生相同的结果:

  

短:min:-32768 max:32767

     

int:min:-2147483648 max:2147483647

     

unsigned int:min:0 max:4294967295

     

long:min:-2147483648 max:2147483647

     

float:min:1.17549e-38 max:   3.40282e + 38

     

double:min:2.22507e-308 max:   1.79769e + 308

     

long double:min:3.3621e-4932 max:   1.18973e + 4932

     

unsigned short:min:0 max:65535

     

unsigned int:min:0 max:4294967295

     

unsigned long:min:0 max:429496729

template<typename T>
void showMinMax()
{
    cout << "min: " << numeric_limits<T>::min() << endl;
    cout << "max: " << numeric_limits<T>::max() << endl;
    cout << endl;
}

int main()
{
cout << "short:";
showMinMax<short>()
...etc...etc..