漂浮小于FLT_MIN。 为什么FLT_TRUE_MIN?
为了看看在浮动下溢的情况下会发生什么,我发现我可以使浮点数比FLT_MIN小得多。 我在OS 10.9上使用xcode 5.1。 语言方言是gnu99。
#include #include #include 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。
- 是否有更有效的方法来certificate数据类型的限制?
- 为什么FLT_MIN实际上不是最小的浮点值? 我应该使用其他常量吗? 输入上一个问题后,我找到了FLT_TRUE_MIN。 这个号码是多少?
获得“低于最低”的2种可能性:
-
float
范围:典型的
float
有2个范围:从FLT_MAX
到FLT_MIN
全精度(正常范围)和从FLT_MAX
到FLT_MIN
精度降低的第二个范围。 这个称为“次正常”的第二个范围通常提供大约10 ^ -7个范围。FLT_TRUE_MIN
是“最小正浮点数”FLT_MIN
是“最小归一化正浮点数”FLT_MIN_10_EXP
是“最小负整数,使得提升到该功率的10在标准化浮点数范围内”C11dr§5.2.4.2.2
通常
0 < FLT_TRUE_MIN <= FLT_MIN <= 10^FLT_MIN_10_EXP <= 10^-37
-
数学表现为
double
。printf()
传递给它的每个float
转换为double
。 C允许代码进行优化,使得传递给printf()
的值可能是FLT_MIN * 0.0000004
的double
乘积。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();
如果没有次正规数,则FLT_MIN
附近的2个几乎相同的数值将具有远低于FLT_MIN
的非零数学差异,并且结果将舍入为0.0
。
对于次正规数,每对不同float
的差值可以用0.0
以外的其他值表示。 **
** + +0.0, -0.0
除外。 签名零有自己的特点。
在非常简单,不精确的术语中,浮点存储为0.xxxxx x 2 ^ yyyyyy。 “正常”数字在xxxxx部分中不需要前导零。 因此,您可以制作的最小数字是0.10000 x 2 ^ -111111。 但是,如果你“欺骗”并非规范化数字,你可以制作一个像0.000001 x 2 ^ -111111,这个更小但有效位数更少。
见http://en.wikipedia.org/wiki/Denormal_number
将y = (+/-) significand x base ^ (exponent - precision)
数和y = (+/-) significand x base ^ (exponent - precision)
表示为浮点数,如果确保significand >= base ^ (precision - 1)
,则每个y != 0
都有唯一的表示forms。 满足此要求的非零y
称为标准化 。 现在FLT_MIN
是最小标准化正float
,而FLT_TRUE_MIN
是没有标准化限制的真正最小值。
换句话说, FLT_MIN = base ^ (FLT_MIN_EXP - 1)
和FLT_TRUE_MIN = base ^ (FLT_MIN_EXP - precision)
。