为什么FLT_MAX和FLT_MIN不是正无穷大和负无穷大,它们的用途是什么?

Why are FLT_MAX and FLT_MIN not positive and negative infinity, and what is their use?

本文关键字:无穷大 FLT 是什么 MIN MAX 为什么      更新时间:2023-10-16

从逻辑上讲,给定浮点数的性质,float的最大可表示值和最小可表示值分别为正无穷和负无穷。

那么,为什么FLT_MAXFLT_MIN没有设置为它们呢?我理解这是"标准所要求的"。但是, FLT_MAXFLT_MIN目前位于float 的可表示数字范围的中间,可以使用吗?其他数值限制也有一些用处,因为它们保证了比较(例如:" INT不能测试大于INT_MAX的值")。没有这样的保证,这些浮动限额有什么用呢?

c++的激励例子:

#include <vector>
#include <limits>
template<typename T>
T find_min(const std::vector<T> &vec)
{
    T result = std::numeric_limits<T>::max();
    for (std::vector<T>::const_iterator p = vec.start() ; p != vec.end() ; ++p)
        if (*p < result) result = *p;
    return result;
}

如果T是整型,这段代码可以正常工作,但如果它是浮点型,则不行。这很烦人。(是的,标准库提供了min_element,但这不是重点。关键是模式)

FLT_MIN/MAX的目的是告诉您可表示的最小和最大的浮点数是什么。无穷大不是一个数字;这是一个极限。

FLT_MAX或FLT_MIN有什么用,因为它们目前位于float的可表示数字范围的中间?

它们不在可表示范围的中间。没有正浮点值x,你可以把它加到FLT_MAX上,得到一个可表示的数字。你会得到+INF。如前所述,它不是一个数字。

如果T是整型,这段代码可以正常工作,但如果它是浮点型,则不行。这很烦人。(是的,标准库提供了min_element,但这不是重点。关键是模式

为什么它不能正常工作呢?它给出了最小的值。它不"正常工作"的唯一情况是;如果表中只包含 +INF。即使在这种情况下,它也会返回一个实际的数字,而不是错误代码。这可能是更好的选择。

FLT_MAX在章节5.2.4.2.2(9)中定义为

最大可表示有限浮点数

正无穷不是有限的

FLT_MIN在章节5.2.4.2.2(10)中定义为

最小归一化正浮点数

负无穷既不归一化也不正。

与整数类型不同,浮点类型(几乎)是关于零的普遍对称的,我认为C浮点模型需要这一点。

在双补系统(即几乎所有现代系统)上,INT_MIN-INT_MAX-1;在其他系统上,可能是-INT_MAX。(诡辩:如果最低的可表示值被视为陷阱表示,则双补系统可以使INT_MIN等于-INT_MAX。)所以INT_MIN传达了INT_MAX本身不能传达的信息。

对于最小的正值的宏并不是特别有用;

另一方面,在浮点数中,最大的负值只有-FLT_MAX(或-DBL_MAX,或-LDBL_MAX)。

至于为什么它们不是无穷大,已经有一种方法来表示无穷大的值(至少在C99中):宏INFINITY。这可能会给一些c++应用程序带来问题,但这些是为C定义的,C没有std::numeric_limits<T>::max()之类的东西。

此外,并不是所有的浮点系统都有无穷大(或NaN)的表示。

如果FLT_MAXINFINITY(在支持它的系统上),那么可能需要另一个宏来表示最大的可表示的实际值。

我想说你看到的破碎模式只是C中糟糕的命名的一个假象,而在使用numeric_limits和模板的c++中,它是一个实际的语义缺陷,破坏了想要处理整数和浮点值的模板代码。当然,你可以写一点额外的代码来测试你是否有一个整数或浮点类型(例如if ((T)1/2) /* floating point */ else /* integer */),问题就解决了。

至于为什么有人会关心FLT_MINFLT_MAX给你的值,它们对于避免下溢和溢出很有用。例如,假设我需要计算sqrt(x²-1)。对于任何大于或等于1的浮点x,这都是定义好的,但是当x很大时,执行平方、减法和平方根很容易溢出并使结果变得毫无意义。您可能想要测试x > FLT_MAX/x是否存在,并以其他方式处理这种情况(例如简单地返回x:-)。