IEEE754標準: 一 , 浮點數(shù)在內(nèi)存中的存儲方式

一. 什么是IEEE754標準

我們知道, 計算機內(nèi)部實際上只能存儲或識別二進制.

在計算機中, 我們?nèi)粘K褂玫奈臋n, 圖片, 數(shù)字等, 在儲存時, 實際上都要以二進制的形式存放在內(nèi)存或硬盤中, 內(nèi)存或硬盤就好像是一個被劃分為許多小格子的容器, 其中每個小格子都只能盛放0或1...

我們?nèi)粘J褂?浮點數(shù) 也不例外, 最終也要被存儲到這樣的二進制小格子中.

這就涉及到了 應該怎么存 的問題, 比如, 對于浮點數(shù) 20.5, 是應該存儲為 0100011 呢, 還是應該存儲為 1100110 呢?

事實上直到20世紀80年代, 還是計算機廠商各自為戰(zhàn), 每家都在設計自己的浮點數(shù)存儲規(guī)則, 彼此之間并不兼容. 直到1985年, IEEE754標準問世, 浮點數(shù)的存儲問題才有了一個通用的工業(yè)標準.

IEEE754標準提供了如何在計算機內(nèi)存中,以二進制的方式存儲十進制浮點數(shù)的具體標準,

IEEE754標準發(fā)布于1985年. 包括 javascript, Java, C在內(nèi)的許多編程語言在實現(xiàn)浮點數(shù)時, 都遵循IEEE754標準.

IEEE754的最新標準是IEEE754-2008, 但本篇文章主要參考的是IEEE754-1985, 好在兩者相差并不大, 而參照1985的標準可以讓我們對一些基礎概念有更好的理解

IEEE754提供了四種精度規(guī)范, 其中最常用的是 單精度浮點型 雙精度浮點型 , 但IEEE754并沒有規(guī)定32位浮點數(shù)類型需要叫做 float, 或64位浮點數(shù)需要叫做 double. 它只是提供了一些關于如何存儲不同精度浮點數(shù)的規(guī)范和標準. 不過一般情況下, 如果我們提到 float, 其實指的就是IEEE754標準中的32位單精度浮點數(shù). 如果我們提到 double, 其實指的就是IEEE754標準中的64位雙精度浮點數(shù)

下面是單精度浮點數(shù)和雙精度浮點數(shù)的一些信息, 可以先簡單看一下, 看不懂也沒關系, 下文會對這里的信息做詳細的解釋...

單雙精度浮點數(shù)對比

好啦, 鋪墊完了, 開始正文吧~


二. 32位單精度浮點數(shù)在內(nèi)存中的存儲方式

上文說到: IEEE754標準提供了如何在計算機內(nèi)存中, 以二進制的方式存儲十進制浮點數(shù)的具體標準, 并制定了四種精度規(guī)范.

這里我們主要研究 32位浮點數(shù) (或者說單精度浮點數(shù), 或者說float類型) 在計算機中是怎么存儲的. 其他精度, 比如64位浮點數(shù), 則大同小異.

想要存儲一個32位浮點數(shù), 比如20.5, 在內(nèi)存或硬盤中要占用32個二進制位 (或者說32個小格子, 32個比特位)

這32個二進制位被劃分為3部分, 用途各不相同:

32位浮點數(shù)內(nèi)存占用示意圖, 共使用了32個小格子

這32個二進制位的內(nèi)存編號從高到低 (從31到0), 共包含如下幾個部分:

sign: 符號位, 即圖中藍色的方塊

biased exponent: 偏移后的指數(shù)位, 即圖中綠色的方塊

fraction: 尾數(shù)位, 即圖中紅色的方塊

下面會依次介紹這三個部分的概念, 用途.


1. 符號位: sign

以32位單精度浮點數(shù)為例, 以下不再贅述:

符號位: 占據(jù)最高位(第31位)這一位, 用于表示這個浮點數(shù)是正數(shù)還是負數(shù), 為0表示正數(shù), 為1表示負數(shù).

舉例: 對于十進制數(shù)20.5, 存儲在內(nèi)存中時, 符號位為0, 因為這是個正數(shù)


2. 偏移后的指數(shù)位: biased exponent

指數(shù)位占據(jù)第30位到第23位這8位. 用于表示以2位底的指數(shù). 至于這個指數(shù)的作用, 后文會詳細講解, 這里只需要知道: 8位二進制可以表示256種狀態(tài), IEEE754規(guī)定, 指數(shù)位用于表示[-127, 128]范圍內(nèi)的指數(shù).

不過為了表示起來更方便, 浮點型的指數(shù)位都有一個固定的偏移量(bias), 用于使 指數(shù) + 這個偏移量 = 一個非負整數(shù). 這樣指數(shù)位部分就不用為如何表示負數(shù)而擔心了. 規(guī)定: 在32位單精度類型中, 這個偏移量是127. 在64位雙精度類型中, 偏移量是1023.

所以這里的偏移量是127,

即, 如果你運算后得到的指數(shù)是 -127, 那么偏移后, 在指數(shù)位中需要表示為: -127 + 127(偏移量) = 0

如果你運算后得到的指數(shù)是 -10, 那么偏移后, 在指數(shù)位中需要表示為: -10 + 127(偏移量) = 117

看, 有了偏移量, 指數(shù)位中始終是一個非負整數(shù).

看到這里, 可能會覺得還不是很清楚指數(shù)的作用到的是什么. 沒關系, 讓我們先繼續(xù)往下看吧...


3. 尾數(shù)位:fraction

尾數(shù)位: 占據(jù)剩余的22位到0位這23位. 用于存儲尾數(shù).

在以二進制格式存儲十進制浮點數(shù)時, 首先需要把十進制浮點數(shù)表示為二進制格式, 還拿十進制數(shù)20.5舉例:

十進制浮點數(shù)20.5 = 二進制10100.1

然后需要把這個二進制數(shù)轉(zhuǎn)換為以2為底的指數(shù)形式:

二進制10100.1 = 1.01001 * 2^4

注意轉(zhuǎn)換時, 對于乘號左邊, 加粗的那個二進制數(shù)1.01001, 需要把小數(shù)點放在左起第一位和第二位之間. 且第一位需要是個非0數(shù). 這樣表示好之后, 其中的1.01001就是尾數(shù).

用 二進制數(shù) 表示 十進制浮點數(shù) 時, 表示為尾數(shù)*指數(shù)的形式, 并把尾數(shù)的小數(shù)點放在第一位和第二位之間, 然后保證第一位數(shù)非0, 這個處理過程叫做規(guī)范化(normalized)

我們再來看看規(guī)范化之后的這個數(shù): 1.01001 * 2^4

其中1.01001是尾數(shù),? 而4就是偏移前的指數(shù)(unbiased exponent), 上文講過, 32位單精度浮點數(shù)的偏移量(bias)為127, 所以這里加上偏移量之后, 得到的偏移后指數(shù)(biased exponent)就是 4 + 127 = 131, 131轉(zhuǎn)換為二進制就是1000 0011

現(xiàn)在還需要對尾數(shù)做一些特殊處理

1. 隱藏高位1.

你會發(fā)現(xiàn), 尾數(shù)部分的最高位始終為1. 比如這里的 1.01001, 這是因為前面說過, 規(guī)范化之后, 尾數(shù)中的小數(shù)點會位于左起第一位和第二位之間. 且第一位是個非0數(shù). 而二進制中, 每一位可取值只有0或1, 如果第一位非0, 則第一位只能為1. 所以在存儲尾數(shù)時, 可以省略前面的 1和小數(shù)點. 只記錄尾數(shù)中小數(shù)點之后的部分, 這樣就節(jié)約了一位內(nèi)存. 所以這里只需記錄剩余的尾數(shù)部分: 01001

所以, 以后再提到尾數(shù), 如無特殊說明, 指的其實是隱藏了整數(shù)部分1. 之后, 剩下的小數(shù)部分

2. 低位補0

有時候尾數(shù)會不夠填滿尾數(shù)位(即圖中的紅色格子). 比如這里的, 尾數(shù)01001不夠23位

此時, 需要在低位補零, 補齊23位.

之所以在低位補0, 是因為尾數(shù)中存儲的本質(zhì)上是二進制的小數(shù)部分, 所以如果想要在不影響原數(shù)值的情況下, 填滿23位, 就需要在低位補零.

比如,? 要把二進制數(shù)1.01在不改變原值的情況下填滿八位內(nèi)存, 寫出來就應該是: 1.010 0000, 即需要在低位補0

同理, 本例中因為尾數(shù)部分存儲的實際上是省略了整數(shù)部分 1. 之后, 剩余的小數(shù)部分, 所以這里補0時也需要在低位補0:

原尾數(shù)是:? ? 01001(不到23位)

補零之后是:? 0100 1000 0000 0000 000? (補至23位)


三. 實例: 表示十進制浮點數(shù)20.5

在上面的討論中, 我們已經(jīng)得出, 十進制浮點數(shù) 20.5 的:

符號位是: 0

偏移后指數(shù)位是: 1000 0011

補零后尾數(shù)位是: 0100 1000 0000 0000 000

現(xiàn)在, 把這三部分按順序放在32位浮點數(shù)容器中, 就是 0? ? 1000 0011? ? 0100 1000 0000 0000 000

這就在32位浮點數(shù)容器中, 以二進制表示了一個十進制數(shù)20.5的方式

這里有一個可以驗證的IEEE754浮點數(shù)內(nèi)存狀態(tài)的網(wǎng)站, 我們來驗證一下:

可見驗證是通過的. 不過為了加深理解, 我們再反向推導一遍:


假設現(xiàn)在我們有一個用二進制表示的32位浮點數(shù): 0? 1000 0011? 0100 1000 0000 0000 000, 求它所代表的十進制浮點數(shù)是多少?

觀察可知:

符號位是0: 所以這是個正數(shù).

尾數(shù)是: 0100 1000 0000 0000 000

去掉后面的補零, 再加上隱藏的整數(shù)部分1.? 得到完整的尾數(shù)(含隱藏的整數(shù)部分)為: 1.01001

偏移后的指數(shù)位為: 1000 0011, 轉(zhuǎn)換為十進制為131, 減去偏移量127, 得到真正的指數(shù)是 4

所以, 最后得到的浮點數(shù) = 尾數(shù)(含隱藏的整數(shù)部分) * 以2為底的指數(shù)次冪

=? 二進制的: 1.01001 * 2^4

=? 把小數(shù)點向右移動4位

=? 二進制的10100.1

=? 十進制位20.5

注意, 直到最后一步才把二進制轉(zhuǎn)換為十進制.

附帶的, 這里還有一個進制轉(zhuǎn)換網(wǎng)站, 可以看到二進制的10100.1, 確實等于十進制的20.5

到這里就講解的差不多了,

隨后是一張大體的計算方法示意圖

還有雙精度類型的內(nèi)存狀態(tài)示意圖:

下一篇會講述為什么32位單精度浮點數(shù)的取值范圍是±1.18*10^{-38} 到? ±3.4 * 10^{38}, 這個值究竟是如何計算出來的...

下一篇再見吧~


注:

這一系列文章其實是我在學習IEEE754標準的過程中, 總結(jié)的一系列筆記. 其中包含了一些個人理解, 所以如有偏差, 還望指出.

整個系列大概會包含如下五篇文章:

一. 浮點數(shù)在內(nèi)存中的存儲方式

二. 浮點數(shù)的取值范圍是如何計算的

三. 浮點數(shù)的精度是如何計算的

四. 非規(guī)格數(shù), ±0, ±infinity和NaN都是什么

五. 浮點數(shù)的舍入規(guī)則(rounding)

下一篇再見~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載蜓氨,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者琼锋。
  • 序言:七十年代末具则,一起剝皮案震驚了整個濱河市差牛,隨后出現(xiàn)的幾起案子鞭执,更是在濱河造成了極大的恐慌项郊,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锰镀,死亡現(xiàn)場離奇詭異娘侍,居然都是意外死亡咖刃,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門私蕾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來僵缺,“玉大人,你說我怎么就攤上這事踩叭】某保” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵容贝,是天一觀的道長自脯。 經(jīng)常有香客問我,道長斤富,這世上最難降的妖魔是什么膏潮? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮满力,結(jié)果婚禮上焕参,老公的妹妹穿的比我還像新娘。我一直安慰自己油额,他們只是感情好叠纷,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著潦嘶,像睡著了一般涩嚣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掂僵,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天航厚,我揣著相機與錄音,去河邊找鬼锰蓬。 笑死幔睬,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的芹扭。 我是一名探鬼主播麻顶,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼冯勉!你這毒婦竟也來了澈蚌?” 一聲冷哼從身側(cè)響起摹芙,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤灼狰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后浮禾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體交胚,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡份汗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝴簇。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片杯活。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖熬词,靈堂內(nèi)的尸體忽然破棺而出旁钧,到底是詐尸還是另有隱情,我是刑警寧澤互拾,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布歪今,位于F島的核電站,受9級特大地震影響颜矿,放射性物質(zhì)發(fā)生泄漏寄猩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一骑疆、第九天 我趴在偏房一處隱蔽的房頂上張望田篇。 院中可真熱鬧,春花似錦箍铭、人聲如沸泊柬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彬呻。三九已至,卻和暖如春柄瑰,著一層夾襖步出監(jiān)牢的瞬間闸氮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工教沾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蒲跨,地道東北人。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓授翻,卻偏偏與公主長得像或悲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子堪唐,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容