如何解决 numeric_limits::min() 定义不一致的问题?

发布于 2024-07-18 03:28:07 字数 662 浏览 8 评论 0 原文

numeric_limits 特征应该是获取各种类型信息的通用方法,能够执行类似的操作

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::min() 返回最小负数,而 numeric_limits::min() 返回最小的数!

有人知道这个设计背后的原理吗? 有没有更好(推荐?)的使用 numeric_limits 的方法? 在上面的特定函数中,我当然可以将 T 初始化为 vect[0],但这不是我正在寻找的答案。

另请参阅(浮点特定)讨论 此处

The numeric_limits traits is supposed to be a general way of obtaining various type infomation, to be able to do things like

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

The problem is that (at least using MS Visual Studio 2008) numeric_limits<int>::min() returns the smallest negative number, while numeric_limits<double>::min() returns the smallest positive number!

Anyone knows the rationalie behind this design? Is there a better (recommended?) way of using numeric_limits? In my specific function above, I could of course initialize T to vect[0], but that is not the answer I am looking for..

See also (floating-point-specific) discussion
here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

寂寞笑我太脆弱 2024-07-25 03:28:07

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

请参阅此处的文档

You can use Boost libraries. The library Numeric Conversions provides a class called bounds that can be used consistently.

See the documentation here.

薄凉少年不暖心 2024-07-25 03:28:07

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

C++11 向 std::numeric_limits 添加了 lowest() 函数 (参见此处

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

This is an old thread, but there is an updated answer:

C++11 added a lowest() function to std::numeric_limits (See here)

So you can now call std::numeric_limits<double>::lowest() to get the lowest representable negative value.

五里雾 2024-07-25 03:28:07

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

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

我怀疑它是出于实际目的而这样定义的。 对于整数,您通常关心上溢/下溢,其中最小值和最大值变得令人感兴趣。

对于浮点数,存在一种不同类型的下溢,因为计算可能会产生大于零但小于该浮点类型的最小可表示小数的值。 了解最小可表示浮点值可以让您解决该问题。 另请参阅有关次正常/非正常数字的维基百科文章。

The behaviour of min() isn't all that strange, it returns FLT_MIN, DBL_MIN or INT_MIN (or their respective values), depending on the type you specialize with. So your question should be why FLT_MIN and DBL_MIN are defined differently from INT_MIN.

Unfortunately, I don't know the answer to that latter question.

My suspicion is that it was defined that way for practical purposes. For integer numbers, you're usually concerned with overflow/underflow, where the minimum and maximum value become of interest.

For floating point numbers, there exists a different kind of underflow in that a calculation could result in a value that's larger than zero, but smaller than the smallest representable decimal for that floating point type. Knowing that smallest representable floating point value allows you to work around the issue. See also the Wikipedia article on subnormal/denormal numbers.

美男兮 2024-07-25 03:28:07

当然

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

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

A workaround would be

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

Of course, this doesn't explain the strange behaviour of numerics_limits::min() which could be a result of the fact that there are different min/max borders for integers (min = -2^n, max = 2^n-1) but not for doubles.

乱了心跳 2024-07-25 03:28:07

我不确定其理由,但这是预期的行为。 好吧,从某种意义上说,这就是 Josuttis(以及大概的标准)所描述的!

min():“最小有限值(最小
浮点的标准化值
具有非规范化的类型)。”

可以最好地判断该类型是否不是整数(numeric_limits<>::is_integer)并且非规范化 (numeric_limits<>::has_denorm) min() 将返回该类型的最小可表示值,否则它将返回最小值 -

对于更一致的界面,请查看 Boost numeric/conversion 库,特别是 bounds 特征类。以下是一个片段:

cout << "lowest float:" << boost::numeric::bounds<float>::lowest();
cout << "lowest int:  " << boost::numeric::bounds<int>::lowest();

您还可以找到 boost::integer 库 很有用。它带来了一些 C99 的整数支持(例如 int_least16_t) 到 C++,可以帮助您选择适合您特定需求的最佳尺寸类型。 举个例子:

boost::uint_t<20>::fast fastest20bits; // fastest unsigned integer that 
                                       // can hold at least 20 bits.
boost::int_max_value_t<100000>::least  // smallest integer that can store
                                       // the value 100000.

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

I'm not sure of the rationale but it is expected behaviour. Well, in the sense that is how Josuttis (and, presumably the standard) describes it!

min(): "Miniumum finite value (minimum
normalized value for floating-point
types with denormalization)."

As best I can tell if the type is not an integer (numeric_limits<>::is_integer) and has denormalization (numeric_limits<>::has_denorm) min() will return the smallest representable value by that type. Otherwise it will return the smallest value - which may be negative.

For a more consistent interface check out the Boost numeric/conversion library. Specifically the bounds traits class. Here's a snippet:

cout << "lowest float:" << boost::numeric::bounds<float>::lowest();
cout << "lowest int:  " << boost::numeric::bounds<int>::lowest();

You may also find the boost::integer library useful. It brings some of C99's integer support (like int_least16_t) to C++ and can help select the best sized type for you particular need. An example:

boost::uint_t<20>::fast fastest20bits; // fastest unsigned integer that 
                                       // can hold at least 20 bits.
boost::int_max_value_t<100000>::least  // smallest integer that can store
                                       // the value 100000.

I often find that when I need one of boost::numeric/conversion or boost::integer I need them both.

尬尬 2024-07-25 03:28:07

numeric_limits::min 返回最小负数,所有浮点数类型,当我尝试使用时返回最小正数孙CC& g++。

我想这是因为“最小”和“最小”对于浮点数来说意味着不同的东西。 不过这有点奇怪。

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

短:最小值:-32768 最大值:32767

整数:最小值:-2147483648 最大值:2147483647

无符号整数:最小值:0 最大值:4294967295

长:最小值:-2147483648 最大值:2147483647

浮点数:最小值:1.17549e-38 最大值:
3.40282e+38

双精度:最小值:2.22507e-308 最大值:
1.79769e+308

长双精度:最小值:3.3621e-4932 最大值:
1.18973e+4932

无符号短:最小值:0 最大值:65535

无符号整数:最小值:0 最大值:4294967295

无符号长整型:最小值:0 最大值: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..

numeric_limits<int>::min returned the lowest negative number, all floating point number types, return the smallest positive number when I tried it with Sun CC & g++.

I guess this is because 'smallest' and 'minimum' mean different things with floating point numbers. It is a bit odd though.

Both Sun CC and g++ produce the same result :

short: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..
趁年轻赶紧闹 2024-07-25 03:28:07

空向量最小值的定义是有争议的。 如果向量为空,则没有最小元素。

更喜欢使用 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;
    }
}

The definition of the smallest value for an empty vector can be argued. If the vector is empty then there is no smallest element.

Prefer to use std::min_element instead:

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文