为什么将 1 添加到 numeric_limits<float>::min() 返回 1?
Why does adding 1 to numeric_limits<float>::min() return 1?
为什么从浮点最大值中减去 1 会返回一个合理的值,而将 1 加到浮点最小值会返回 1?
我认为,如果您添加或减去小于该特定幅度的epsilon的值,那么什么都不会发生,也不会增加或减少。
这是我使用 g++ 编译的代码,没有标志并在x86_64上运行。
#include <limits>
#include <iostream>
int main() {
float min = std::numeric_limits<float>::min() + 1;
float max = std::numeric_limits<float>::max() - 1;
std::cout << min << std::endl << max << std::endl;
return 0;
}
输出此内容:
1
3.40282e+38
我希望它输出这个:
-3.40282e+38
3.40282e+38
std::numeric_limits<float>::min()
返回最小的规范化正值。若要获取没有低于该值的值,请使用std::numeric_limits<float>::lowest()
。
https://en.cppreference.com/w/cpp/types/numeric_limits/min
>min
是最小幅度的正归一化浮点数,是一个非常小的正数(大约1.17549e-38
(,而不是具有大幅度的负数。 请注意,-
在指数中,这是科学记数法。e-38
表示小数点后 38 个零。 在 https://www.h-schmidt.net/FloatConverter/IEEE754.html 上尝试一下,以在二进制float
中播放位。
std::numeric_limits<float>::min()
是最小星等归一化float
,而不是-max
。 CppReference甚至有一个注释,说明这可能令人惊讶。
你知道为什么选择它作为min((的值而不是最低的负值吗?对于所有其他类型来说,似乎是一个异常值。
lowest
和denorm_min
等numeric_limits<T>
中的一些复杂功能在C++11中是新的。 大多数定义内容的选择大多遵循C。 历史上的C重视经济,并没有定义很多不同的名称。 (在古老的计算机上越小越好,而且全局命名空间中的内容也越少,这是 C 可以访问的所有内容。
浮点类型通常是1在 0 附近对称(符号/幅度表示(,因此 C 没有针对最负浮点数/双精度/长双精度的单独命名常量。 只需FLT_MAX
和FLT_MIN
CPP 宏。 C 没有模板,因此您知道何时编写 FP 代码,并在必要时对适当的常量使用-
。
如果您只打算使用几个命名常量,那么最有趣的三个是:
FLT_EPSILON
告诉您可用的精度(尾数位(:nextafter(1.0, +INF) - 1.0
-
有限浮点数的
FLT_MIN
/FLT_MAX
分钟(归一化(和最大幅度。 这主要取决于浮点数有多少指数位。它们在 1.0 附近不太对称,原因有两个:FLT_MAX 中的全一尾数,以及逐渐下溢(次正态(占据最低指数场(带偏差为 0(,但
FLT_MIN
忽略次正态。 对于二进制 32float
,FLT_MIN * FLT_MAX
约为 3.99999976 IEEE754。 (出于性能原因,您通常希望避免次正态,因此您有逐渐下溢的空间,因此FLT_MIN不denorm_min
是有道理的(
(有趣的事实:0.0
是次正规的特例:指数场 = 0 表示尾数为 0.xxx 而不是 1.xxx(。
脚注 1:CppReference 指出,C++11std::numeric_limits<T>::lowest()
可能与第 3 方 FP 类型的-max
不同,但不适用于标准 C++ FP 类型。
lowest
就是你想要的:最负的有限值。 它在整数和 FP 类型中是一致的,因为它是最负的值,因此例如,您可以将其用作模板化搜索循环的初始值设定项,该循环使用std::min
查找数组中的最低值。
C++11还引入了denorm_min
,即FP类型的最小正次正规值,即非正规值。 在IEEE754中,对象表示的所有位均为 0,但尾数低位中的 1 除外。
1.0 + 1.17549e-38
(四舍五入到最接近的float
后(的浮点数结果正好是1.0
。min
低于std::numeric_limits<float>::epsilon
因此,当添加到1.0
时,整个更改将因舍入误差而丢失。
因此,即使您确实以全精度打印浮点数(或作为十六进制浮点数(,它也将是1.0
。 但是您只是使用默认格式打印cout
该格式舍入到一些有限的精度,例如 6 个十进制数字。 https://en.cppreference.com/w/cpp/io/manip/setprecision
(该问题的早期版本包括min
~= 1.17549e-38的数值;这个答案开始解决这种混淆,我没有费心完全重写这些部分(。
- EASTL矢量<向量<int>>连续的
- 如何使用std::min和std::less返回对象
- 为什么 -mmacosx-version-min=10.10 不阻止使用标记为从 10.11 开始的函数?
- 关于 std::min, std::max 中的比较运算符的混淆
- 使用 CImg 库的 std::min 和 std::max 的编译问题
- 为什么将 1 添加到 numeric_limits<float>::min() 返回 1?
- 在儿童的特定情况下,向下渗透MIN二进制堆失败
- 在f2c.h文件中定义min()max()宏时出错
- 如何解决g++问题"internal compiler error: Illegal instruction min() _GLIBCXX_USE_NOEXCEPT { return __FLT_MI
- 第 5 行:字符 54:错误:调用"min(int,std::__cxx11::basic_string<char>::size_type)"没有匹配函数
- 如何使用函数std::min()来计算最小值
- 在函数 'int main(int, char**) 中,没有声明 'MIN'
- 将迭代器值与 std::min 一起固定到 end()
- C++是否在 std::min 和 std::max 下标准化 std::optional 的行为?
- c++ 中 std::min 的效率
- 当摆脱模偏差时,min = -upper_bound % upper_bound; // 如何工作?
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- std :: min-设计考虑
- 如何在 OpenACC 中并行化内部具有"min"功能的循环
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错