为了看看在浮动下溢的情况下会发生什么,我发现我可以使浮点数比FLT_MIN小得多。我在OS 10.9上使用xcode 5.1。语言方言是gnu99。
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
int main(int argc, const char * argv[])
{
float underflow = FLT_MIN * 0.0000004;
printf("Float min is %f or %e.\nUnderflow is %f or %e\nMin float exp is %d.\n", FLT_MIN, FLT_MIN, underflow, underflow, FLT_MIN_10_EXP);
return 0;
}
打印:
浮点数为0.000000或1.175494e-38
下溢为0.000000或4.203895e-45
Min float exp是-37。
答案 0 :(得分:7)
获得“低于最低限度”的两种可能性:
float
范围:
典型float
个数字有2个范围:从FLT_MAX
到FLT_MIN
的完整精度(正常范围)和从FLT_MIN
到{{的精度降低的第二个范围1}}。第二个范围,称为“次正常”,通常提供大约10 ^ -7个范围。
FLT_TRUE_MIN
是“最小正浮点数”
FLT_TRUE_MIN
是“最小标准化正浮点数”
FLT_MIN
是“最小负整数,使得提升到该幂的10在标准化浮点数范围内”C11dr§5.2.4.2.2
一般FLT_MIN_10_EXP
数学表现为0 < FLT_TRUE_MIN <= FLT_MIN <= 10^FLT_MIN_10_EXP <= 10^-37
。
double
会将传递给printf()
的每个float
转换为double
。 C允许代码进行优化,以便传递给printf()
的值可能是double
的{{1}}乘积。
FLT_MIN * 0.0000004
如果输出为float underflow = FLT_MIN * 0.0000004;
printf("%e\n", underflow);
而不是4.701976e-45
,情况就是这样。
关于“次正常”的注释。 次正规(或非正规)数字的一个令人信服的原因在于以下问题。
4.203895e-45
如果没有次正规数,则float a,b;
... // somehow a and b are set.
// Are the 2 below equivalent?
if (a == b) foo();
if ((a - b) == 0) foo();
附近的2个几乎相同的数值将具有非零数学差异,远低于FLT_MIN
,结果将舍入为FLT_MIN
。
对于次正规数,每对不同0.0
s的差异可由float
以外的其他内容表示。 **
** 0.0
除外。签名零有自己的特点。
答案 1 :(得分:3)
在非常简单,不精确的术语中,浮点存储为0.xxxxx x 2 ^ yyyyyy。 &#34;正常&#34;数字必须在xxxxx部分中没有前导零。因此,您可以制作的最小数字是0.10000 x 2 ^ -111111。但是,如果你&#34;作弊&#34;并且可以使你的数字非规范化,例如0.000001 x 2 ^ -111111,它更小但有效位数更少。
答案 2 :(得分:1)
如果您确定y = (+/-) significand x base ^ (exponent - precision)
,则表示浮动数字为y != 0
,每个significand >= base ^ (precision - 1)
都有唯一的代表。满足此要求的非零y
称为规范化。现在FLT_MIN
是最低标准化正数float
,而FLT_TRUE_MIN
是没有标准化限制的真正最低值。
换句话说,FLT_MIN = base ^ (FLT_MIN_EXP - 1)
和FLT_TRUE_MIN = base ^ (FLT_MIN_EXP - precision)
。