官术网_书友最值得收藏!

建議4-2:浮點數轉換為新類型時必須做范圍檢查

關于浮點類型數據的轉換原則,在C99的6.3.1.4節與6.3.1.5節中做了非常重要的闡述,其表達的主要意思如下:

當我們將一個浮點類型的數據轉換成除_Bool類型之外的一個整型數據時,該浮點數的小數部分須被丟棄,只保留它的整數部分。如果浮點數整數部分的值無法使用這種整型表示方法時,其行為是未定義的。

與此同時,如果我們將一個整數類型的數據轉換成一個浮點類型時,如果該整型數據的值在該浮點數的取值范圍內,并且能夠被浮點類型精確表示,那么將會被正確轉換;如果該整型數據的值在該浮點數的取值范圍內,但不能夠被浮點類型精確表示,那么轉換的結果是最鄰近的稍大或者稍小的可表示值;但如果該整型數據的值在該浮點數的取值范圍外,其行為是未定義的。

當我們將一個double類型降級轉換為float類型、將long double類型降級轉換到double或者float類型時,如果轉換的值在新類型的取值范圍內,并且能夠被新類型精確表示,那么將會被正確轉換;如果轉換的值在新類型的取值范圍內,但不能夠被新類型精確表示,那么轉換的結果是最鄰近的稍大或者稍小的可表示值;但如果轉換的值在新類型的取值范圍外,其行為是未定義的。

由此可見,為了避免浮點數據轉換時導致的未定義行為,我們應該在轉換時對數據進行相關的范圍檢查。例如,下面的代碼清單1-23演示了如何將double類型轉換為int類型。

代碼清單1-23 double轉換為int類型示例


#include <stdio.h>
#include<limits.h>
int main(void)
{
    double d1=2147483648.01;
    int i1=0;
    if(d1>(double)INT_MAX||d1<(double)INT_MIN)
    {
    }
    else
    {
            i1=(int)d1;
    }
    printf("i1=%d\n",i1);
    return 0;
}

在上面的程序中,我們通過語句“if(d1>(double)INT_MAX||d1<(double)INT_MIN)”來對程序做類型轉換時的取值范圍檢查,這樣就可以避免在執行語句“i1=(int)d1”時發生未定義行為。

但需要特別強調的是,上面的程序是建立在double類型的取值范圍大于int類型的取值范圍的基礎之上的。因此,在使用這種方法做取值范圍檢查時,你必須完全明白不同編譯器所對應的相關類型的取值范圍。假設在某個編譯器中,double類型的取值范圍小于int類型的取值范圍,那么上面這種方法將是不可行的,實際上這種情況基本沒有。

相對于浮點數與整數之間的轉換,浮點數與浮點數之間的轉換就簡單多了。演示示例如代碼清單1-24所示。

代碼清單1-24 double與float類型轉換示例


#include <stdio.h>
#include<limits.h>
#include<float.h>
int main(void)
{
    long double ld1=1.7976931348623158e+308;
    double d1=1.0;
    double d2=1.0;
    float f1=1.0f;
    float f2=1.0f;
    /*double->float*/
    if(d1>FLT_MAX||d1<FLT_MIN)
    {
    }
    else
    {
            f1=(float)d1;
    }
    /*long double->double*/
    if(ld1>DBL_MAX||ld1<DBL_MIN)
    {
    }
    else
    {
            d2=(double)ld1;
    }
    /*long double->float*/
    if(ld1>FLT_MAX||ld1<FLT_MIN)
    {
    }
    else
    {
            f2=(float)ld1;
    }
    return 0;
}

主站蜘蛛池模板: 图木舒克市| 资阳市| 老河口市| 舞阳县| 正宁县| 霍山县| 大新县| 仲巴县| 固安县| 蕲春县| 宁武县| 渝北区| 泾阳县| 宜昌市| 阿尔山市| 西峡县| 扶余县| 汉川市| 浙江省| 新泰市| 新巴尔虎左旗| 辽阳市| 错那县| 阿拉尔市| 连南| 大庆市| 兖州市| 平阳县| 大石桥市| 军事| 米脂县| 益阳市| 天台县| 钟山县| 乌什县| 巩义市| 成都市| 房产| 宜章县| 兴宁市| 沁水县|