我想直接计算该float
类型的最小值,这是我的算法(假设浮点数的编码符合IEEE 754标准):
#include <math.h>
#include <limits.h>
#include <float.h>
#include <stdio.h>
float float_min()
{
int exp_bit = CHAR_BIT * sizeof(float) - FLT_MANT_DIG;
float exp = 2 - pow(2, exp_bit - 1);
float m = pow(2, -(FLT_MANT_DIG - 1));
return m * pow(2, exp);
}
int main()
{
printf("%g\n", float_min());
}
Run Code Online (Sandbox Code Playgroud)
输出是1.4013e-45
.不过,我觉得值了FLT_MIN
的C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\float.h
是1.175494351e-38F
.谁错了?
Pet*_*ker 41
虽然此问题已被多次提出并回答,但我认为没有任何答案是正确的.关键是这FLT_MIN
是可以表示的最小标准化值.回到过去那些重要的事情.然后英特尔出现并引入了次正规值,这会降低精度,以便表示接近0的值.次正规是具有最小指数的值和高位全为零的分数.由此得出,最小的非零次正规值除了最低位(即1)之外都有一个全零的分数.这是可以表示的最小值,但是当你在那里时,在这里改变一下并且价值发生了很大的变化,因此必须非常小心地使用这些东西.
编辑,澄清"规范化":
假设我们正在写小数值:6.02x10 ^ 23,.602*10 ^ 24,60.2*10 ^ 22.这些都代表相同的价值,但它们显然看起来不同.因此,让我们引入一个写十进制值的规则:每个值必须在小数点左边只有一个非零数字.因此,该值的"标准化"形式为6.02x10 ^ 23,如果我们有一个以非标准化形式写的值,我们可以移动小数点并调整指数以保留该值并将其置于标准化形式.
IEEE浮点执行相同的操作:规则是分数的高位必须始终为1,并且任何计算都必须调整其结果的分数和指数以满足该规则.
当我们编写非常接近0的十进制值时,这不是问题:我们可以使指数尽可能小,因此我们可以编写类似6.02*10 ^ -16384的数字.对于浮点值,我们不能这样做:有一个我们不能低于的最小指数.为了允许更小的值,IEEE要求说当指数是最小的可表示值时,分数不必被标准化,也就是说,它不必在其高位中具有1.在写十进制值时,就像说我们可以在小数点左边有一个0.因此,如果我们的十进制规则表示最低允许指数为-100,则最小标准化值为1.00x10 ^ -100,但较小值可表示为非标准化:0.10*10 ^ -100,0.01*10 ^ - 100等
现在为我们的十进制规则添加一个要求,我们只能有三个数字:小数点左边一个,右边两个.这就像浮点部分,因为它具有固定的位数.因此,对于小的正常值,我们有三个数字可以使用:1.23*10 ^ -100.对于较小的值,我们使用前导零,其余数字的精度较低:0.12*10 ^ -100有两位数,0.01*10 ^ -100只有1.这也是浮点次正规的工作方式:你得到更少和当你越远越低于最小标准化值时,有效位越少,直到你用完了比特并得到0.
编辑:为了澄清术语,IEEE-754标准提到那些大于0且小于最小标准化值的值作为非正规数 ; 最新版本的IEEE-754将它们称为次正规.他们的意思是一样的.
ikl*_*kov 16
你的结果1.4013e-45
是非正规的最小正浮点值,也称为FLT_TRUE_MIN
等于1.401298464e-45F
.
FLT_MIN
是规范化的最小正浮点值(1.175494351e-38F
)
归档时间: |
|
查看次数: |
1429 次 |
最近记录: |