[英]floats smaller than FLT_MIN. why FLT_TRUE_MIN?
試圖看看在浮動下溢的情況下會發生什么,我發現我可以使浮點數比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。
獲得“低於最低”的2種可能性:
float
范圍:
典型float
數字有2個范圍:全精度(正常范圍)從FLT_MAX
降至FLT_MIN
和第二范圍與來自還原精度FLT_MIN
降至FLT_TRUE_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,這個更小但有效位更少。
將y = (+/-) significand x base ^ (exponent - precision)
數和y = (+/-) significand x base ^ (exponent - precision)
表示為浮點數,如果確保significand >= base ^ (precision - 1)
,則每個y != 0
都有唯一的表示。 滿足此值的非零y
稱為標准化 。 現在FLT_MIN
是最小標准化正float
,而FLT_TRUE_MIN
是沒有標准化限制的真正最小值。
換句話說, FLT_MIN = base ^ (FLT_MIN_EXP - 1)
和FLT_TRUE_MIN = base ^ (FLT_MIN_EXP - precision)
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.