2016-05-12 90 views
2

我正在解決處理float下溢的C Primer Plus練習之一。任務是模擬它。我就是這麼做的:C語言中的浮點下溢

#include<stdio.h> 
#include<float.h> 

int main(void) 
{ 
    // print min value for a positive float retaining full precision 
    printf("%s\n %.150f\n", "Minimum positive float value retaining full precision:",FLT_MIN); 

    // print min value for a positive float retaining full precision divided by two 
    printf("%s\n %.150f\n", "Minimum positive float value retaining full precision divided by two:",FLT_MIN/2.0); 

    // print min value for a positive float retaining full precision divided by four 
    printf("%s\n %.150f\n", "Minimum positive float value retaining full precision divided by four:",FLT_MIN/4.0); 

    return 0; 
} 

結果是

Minimum positive float value retaining full precision:     0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625000000000000000000000000 
Minimum positive float value retaining full precision divided by two: 0.000000000000000000000000000000000000005877471754111437539843682686111228389093327783860437607543758531392086297273635864257812500000000000000000000000 
Minimum positive float value retaining full precision divided by four: 0.000000000000000000000000000000000000002938735877055718769921841343055614194546663891930218803771879265696043148636817932128906250000000000000000000000 

我預期分鐘浮點值除以精度要求不高由兩個和四個,但它似乎精度是確定的,沒有下溢的情況。這怎麼可能?我錯過了什麼?

非常感謝您

+0

參數不匹配的原型函數的參數進行默認的促銷活動。 –

+0

@Kerrek SB您的評論是真實的,但不會影響OP所謂缺乏「期望精度更低」,如果代碼使用IEEE 754 [binary32](https://en.wikipedia.org/wiki/Single-precision_floating-point_format )。 – chux

回答

1

由2

評估精度代碼的簡單劃分FLT_MIN(當然是2的冪),而不是用一個數字,僅高於2的冪開始的不正確的方法,這樣它的二進制significand就像1.000...(maybe total of 24 binary digits)...0001。保證值打印原本是float。 (FLT_MIN/2.0double。)下面

注意,當數字變得小於FLT_MIN精度丟失:最小標準化正的浮點數。

還可以考慮FLT_TRUE_MIN:最小正浮點數。見binary32

#include <float.h> 
#include <math.h> 
#include <stdio.h> 

int main(void) { 
    char *format = "%.10e %a\n"; 
    printf(format, FLT_MIN, FLT_MIN); 
    printf(format, FLT_TRUE_MIN, FLT_TRUE_MIN); 

    float f = nextafterf(1.0f, 2.0f); 
    do { 
    f /= 2; 
    printf(format, f, f); // print in decimal and hex for detail 
    } while (f); 
    return 0; 
} 

輸出

1.1754943508e-38 0x1p-126 
1.4012984643e-45 0x1p-149 

5.0000005960e-01 0x1.000002p-1 
2.5000002980e-01 0x1.000002p-2 
1.2500001490e-01 0x1.000002p-3 
... 
2.3509889819e-38 0x1.000002p-125 
1.1754944910e-38 0x1.000002p-126 
5.8774717541e-39 0x1p-127 // lost least significant bit of precision 
2.9387358771e-39 0x1p-128 
... 
2.8025969286e-45 0x1p-148 
1.4012984643e-45 0x1p-149 
0.0000000000e+00 0x0p+0