为什么numeric_limits <float> :: min()实际上没有给出可能的最小浮点数?

时间:2018-01-04 01:07:18

标签: c++ floating-point

似乎我们可以简单地推导出小于numeric_limits<float>::min()的浮点数。为什么。如果numeric_limits<float>::min()不应该是最小的正浮点数,它应该是什么?

#include <iostream>
#include <limits>
using namespace std;

int main(){
    float mind = numeric_limits<float>::min();
    float smaller_than_mind = numeric_limits<float>::min()/2;
    cout<< ( mind > smaller_than_mind && smaller_than_mind > 0 ) <<endl;
}

在此处运行:https://onlinegdb.com/ry3AcxjXz

3 个答案:

答案 0 :(得分:7)

浮点类型的

min()返回具有格式的完整表达能力的最小正值 - 其有效位的所有位都可以使用。

较小的正值称为次正规值。虽然它们是可表示的,但有效数字的高位必须为零。

IEEE-754 64位二进制浮点格式表示带符号的数字(+或 - ,编码为0或1),指数(-1022到+1023,编码为1到2046,加0)和2047作为特殊情况),以及53位有效数字(用52位编码加上指数字段的线索)。

对于正常值,指数字段为1到2046(表示-1022到+1023的指数),有效数字(二进制​​)是1.xxx ... xxx,其中xxx ... xxx表示52个以上的位。在所有这些值中,有效数字的最低位的值是最高有效位(其中的第一个)的值的2 -52

对于次正规值,指数字段为0.这仍然表示-1022的指数,但它表示有效数字的高位为0.有效数字现在为0.xxx ... xxx。由于在该范围内使用了较低和较低的值,因此有效数的更多前导位变为零。现在,有效数字的最低位的值大于最高有效位的值的2 -52 。您不能像在正常间隔中那样精确调整此区间中的数字,因为并非所有有效位的位都可用于任意值 - 某些前导位固定为0以设置比例。

因此,处理此范围内的数字时出现的相对误差往往大于正常范围内的相对误差。浮点格式具有这个低于正常范围,因为如果没有,则数字将在最小的正常值处切断,并且该正常值与零之间的差距将是一个巨大的相对跳跃 - 该值的100%一步到位。通过包含次正规数,相对误差逐渐增加,绝对误差从这一点保持不变,直到达到零。

了解正常范围的底部非常重要。 min()告诉你这个。 denorm_min()告诉您最终的最小正值。

答案 1 :(得分:3)

根据en.cppreference.com

  

对于具有非规范化的浮点类型,min返回最小值   正标准化值。请注意,此行为可能是意外的,   特别是与整数类型的min行为相比时。

RewriteRule ^user/(.*) user.php?u=$1 [QSA] RewriteRule ^([^\.]+)$ $1.php [NC,L] 是一个在归一化浮点数上具有非规范化information的类型。

答案 2 :(得分:2)

因为numeric_limits::min返回“对于具有次正规数的浮点类型,返回最小正标准化值”。您可以将其除以2并在某些系统上获得次正常(在某些平台上也称为 denormal )数字。这些数字不存储float类型的完整精度,但允许存储原本会变为0.0的值。