爲何 PHP 和 JavaScript 取整 ((0.1+0.7)*10) 的結果不是 8?

php 代碼 php

intval((0.7+0.1)*10)

js 代碼
parseInt((0.7+0.1)*10)
上面的結果都等於 7 這是爲何?
爲何 0.2+0.6 等等就不會這樣? 

剛纔測試了彷佛跟語言不要緊,全部語言都這樣。 app

這和計算機的小數表示有關,

一般狀況下,小數是用 浮點數 表示的:
測試

計算機中的浮點數
浮點指的是帶有小數的數值,浮點運算便是小數的四則運算,經常使用來測量電腦運算速度。大部份計算機採用二進制(b=2)的表示方法。 (bit)是衡量浮點數所需存儲空間的單位,一般爲32位或64位,分別被叫做 單精度雙精度

好比單精度的浮點數,由32個bit位。按照 IEEE 754  標準,32位中有
1位是符號位(sign)
8位是指數位(exponent)
23位是數值 (fraction)

以下圖所示:
那麼這個數的數值就是
(-1)^{sign} \times 2^{exponent_{2}} \times fraction_{2}
這樣好比對於0.5,就能夠表示成sign = 0, exponent = -1, fraction = 1
但實際上 IEEE 754 對錶示方法還作了一些優化,好比fraction必須是1-2之間的一個小數,這樣fraction就只用表示小數位,而exponent的實際值是exponent + offset.

這樣實際的計算公式是: (-1)^{sign} \times 2^{exponent_{2} - 127_{10}} \times (1 + fraction_{2})
好比0.5的float表示爲:
0 01111110 000 00000000 00000000 0000
其中0爲符號位
01111110爲指數位,十進制爲126, 因此實際的exponent爲126 - 127 = -1,
而 000 00000000 00000000 0000 爲fraction,十進制爲0,
因此0.5f =  (-1)^{0} \times 2^{126 - 127} \times (1 + 0_{2})

這種表示方法帶來的問題就是不少浮點數不能精確表示,好比0.1的浮點數表示爲:
0 0111101 110011001100110011001101
實際上值爲 (-1)^{0} \times 2^{123- 127} \times (1 + 10011001100110011001101_{2})\approx 0.10000000149011612
相關文章
相關標籤/搜索