为什么从float max中减去1会返回一个合理的值,而在float min中加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()
.
min
是最小量级的正向归一化浮点数,是一个非常微小的正数(约为 1.17549e-38
),而不是幅度很大的负数。. 请注意 -
是在指数中,这是科学的符号。 e-38
意思是小数点后有38个零。 试着在 https:/www.h-schmidt.netFloatConverterIEEE754.html 在二进制中玩弄位 float
.
std::numeric_limits<float>::min()
是最小值 幅度 归一化 float
,不 -max
. CppReference 甚至有一个关于这可能是令人惊讶的说明。
你知道为什么选择这个值作为min()的值而不是最低的负值吗?与其他类型相比,这似乎是一个异常值。
中的一些复杂性。numeric_limits<T>
喜欢 lowest
和 denorm_min
是C++11中新增加的,定义什么的选择大多沿袭了C,历史上C重视经济,没有定义很多不同的名字。 (在古代的计算机上,小的比较好,也少了全局命名空间的东西,而全局命名空间是C所能接触到的)。
浮点数类型通常是1 0附近对称(signmagnitude表示),所以C语言没有为最负的float double long double单独命名常数。 只是 FLT_MAX
和 FLT_MIN
CPP宏。 C语言没有模板,所以你知道你在写FP代码的时候,可以用一个 -
如果需要的话,可以在适当的常量上使用。
如果你只需要几个命名的常量,那么最有趣的三个常量是。
FLT_EPSILON
告诉你可用的精度 (mantissa 位): nextafter(1.0, +INF) - 1.0
FLT_MIN
FLT_MAX
最小(标准化)和最大的有限浮点数。 这主要取决于一个浮子有多少指数位。
它们在1.0附近不太对称,原因有二:FLT_MAX中的全一元万字符,以及渐进的下溢(次正态)占据了最低的指数场(0与偏置),但 FLT_MIN
忽略次正态。 FLT_MIN * FLT_MAX
是约3.99999976的 IEEE754二进制32 float
. (出于性能的考虑,你通常要避免亚正常值,所以你有逐渐下流的空间,所以FLT_MIN不是有意义的 denorm_min
)
(有趣的是。0.0
是亚正态的一个特例:指数场=0,意味着0.xxx而不是1.xxx的万字符)。)
脚注1: CppReference 指出,C++11 std::numeric_limits<T>::lowest()
可以 有别于 -max
用于第三方FP类型,但不是用于标准的C++ FP类型。
lowest
是 你想要的:最负的有限值。 它在整数和FP类型中是一致的,因为它是最负值,所以例如,你可以将它作为一个模板化搜索循环的初始化器,使用 std::min
来寻找一个数组中的最低值。
C++11还引入了 denorm_min
,是FP类型的最小正次正态值,又称去正态值。 在IEEE754中,对象表示法除了万字符的低位有1之外,其他位都是0。
浮点数的结果是 1.0 + 1.17549e-38
(四舍五入后) float
)正是 1.0
. min
低于 std::numeric_limits<float>::epsilon
所以,当加入到 "四舍五入 "时,整个变化会因四舍五入错误而丢失。1.0
.
因此,即使你用全精度打印浮点数(或作为一个十六进制浮点数),它也会是 1.0
. 但你只是用默认的格式来打印。cout
其中,四舍五入到一些有限的精度,比如小数点后6位。 https:/en.cppreference.comwcppiomanipsetprecision。
(该问题的早期版本包括数值为 min
~=1.17549e-38;这个答案一开始就是为了解决这个混淆的问题,我还没有去完全重写这些部分)。)