浮點數(shù)陷阱

演示代碼

    #include<stdio.h>

    int main () {
        double i;
        for (i = 0; i != 1; i += 0.1) {
            printf ("%lf\n", i);
        }
        return 0;
      }

大家可以先猜想下結(jié)果。

結(jié)果

打印結(jié)果.jpg

倒數(shù)第三行可以看到我強制退出了程序,否則會一直打印。為什么這樣呢?0.1累加十次之后,不應(yīng)該是1.0嗎?

原因

1、浮點數(shù)表示方法

根本原因是不清楚浮點數(shù)的表示方法。

  • 二進制格式

先來說下浮點數(shù)的二進制格式,單精度浮點數(shù)采用32位bits表示,雙精度浮點數(shù)采用64位bits表示。分為三部分,符號位(S)、階碼(E)和尾數(shù)(M)。

single precision:1位符號位,8位階碼,23位尾數(shù)
double precision:1位符號位,11位階碼,32位尾數(shù)

符號位1表示負數(shù),0表示正數(shù)。

  • IEEE754

IEEE754標準中,規(guī)格化的浮點數(shù)真值表示為:
x =(?1)s * (1.M) *2e

其中E = [e]移碼 - 1,階碼的移碼即把補碼標志位取反,為了能表示正負無窮大。由于尾數(shù)高位恒為1,所以只存儲浮點數(shù)位M。

  • 舉個栗子

給出十進制數(shù)-4.25的機器碼,使用單精度

-4.25 = [-100.01]2,符號位為1,尾數(shù)為 1.0001,指數(shù)為2,

所以尾數(shù)域二進制碼

M = [000 1000 0000 0000 0000 0000]2

階碼

E = [2]移碼 - 1 = [1000 0010]2 - 1 = [1000 0001]

得到機器碼為

-4.5 = [1100 0000 1000 1000 0000 0000 0000 0000]2

結(jié)論

浮點數(shù)不能精確表示某些十進制數(shù),只能取無限近似值。將累加值換為0.5,則程序只打印兩次值。

示例代碼中的0.1的累加,則是其近似值的累加,所以不會命中 1 ,程序會一直執(zhí)行下去。

參考

IEEE754浮點數(shù)的表示方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容