最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

淺談JavaScript中小數(shù)和大整數(shù)的精度丟失

 更新時(shí)間:2016年05月31日 09:17:19   投稿:jingxian  
下面小編就為大家?guī)硪黄獪\談JavaScript中小數(shù)和大整數(shù)的精度丟失。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

先來看兩個(gè)問題:

0.1 + 0.2 == 0.3; // false
9999999999999999 == 10000000000000000; // true

第一個(gè)問題是小數(shù)的精度問題,在業(yè)界不少博客里已有討論。第二個(gè)問題,去年公司有個(gè)系統(tǒng)的數(shù)據(jù)庫在做數(shù)據(jù)訂正時(shí),發(fā)現(xiàn)有部分?jǐn)?shù)據(jù)重復(fù)的詭異現(xiàn)象。本文將從規(guī)范出發(fā),對(duì)上面的問題做個(gè)小結(jié)。

最大整數(shù)

JavaScript 中的數(shù)字是用 IEEE 754 雙精度 64 位浮點(diǎn)數(shù) 來存儲(chǔ)的,其格式為:

s x m x 2^e

s 是符號(hào)位,表示正負(fù)。 m 是尾數(shù),有 52 bits. e 是指數(shù),有 11 bits. 在 ECMAScript 規(guī)范 里有給出 e 的范圍為 [-1074, 971]. 這樣,很容易推導(dǎo)出 JavaScript 能表示的最大整數(shù)為:

1 x (2^53 - 1) x 2^971 = 1.7976931348623157e+308

這個(gè)值正是 Number.MAX_VALUE

同理可推導(dǎo)出 Number.MIN_VALUE 的值為:

1 x 1 x 2^(-1074) = 5e-324

注意 MIN_VALUE 表示最接近 0 的正數(shù),而不是最小的數(shù)。最小的數(shù)是 -Number.MAX_VALUE

小數(shù)的精度丟失

JavaScript 的數(shù)字都是雙精度浮點(diǎn)數(shù),在計(jì)算機(jī)里用二進(jìn)制存儲(chǔ)。當(dāng)有效位數(shù)超過 52 位時(shí),會(huì)存在精度丟失。比如:

十進(jìn)制 0.1 的二進(jìn)制為 0.0 0011 0011 0011 … (循環(huán) 0011)
十進(jìn)制 0.2 的二進(jìn)制為 0.0011 0011 0011 … (循環(huán) 0011)
0.1 + 0.2 相加可表示為:
   e = -4; m = 1.10011001100...1100(52 位)
 + e = -3; m = 1.10011001100...1100(52 位)
---------------------------------------------
   e = -3; m = 0.11001100110...0110
 + e = -3; m = 1.10011001100...1100
---------------------------------------------
   e = -3; m = 10.01100110011...001
---------------------------------------------
 = 0.01001100110011...001
 = 0.30000000000000004(十進(jìn)制)

根據(jù)上面的演算,還可以得出一個(gè)結(jié)論:當(dāng)十進(jìn)制小數(shù)的二進(jìn)制表示的有限數(shù)字不超過 52 位時(shí),在 JavaScript 里是可以精確存儲(chǔ)的。比如:

0.05 + 0.005 == 0.055 // true

進(jìn)一步的規(guī)律,比如:

0.05 + 0.2 == 0.25 // true
0.05 + 0.9 == 0.95 // false

需要考慮 IEEE 754 的 Rounding modes, 有興趣的可進(jìn)一步研究。

大整數(shù)的精度丟失

這個(gè)問題鮮有人提及。首先得弄清楚問題是什么:

1. JavaScript 能存儲(chǔ)的最大整數(shù)是什么?

該問題前面已回答,是 Number.MAX_VALUE, 非常大的一個(gè)數(shù)。

2. JavaScript 能存儲(chǔ)的且不丟失精度的最大整數(shù)是什么?

根據(jù) s x m x 2^e, 符號(hào)位取正,52 位尾數(shù)全填充 1, 指數(shù) e 取最大值 971, 顯然,答案依舊是 Number.MAX_VALUE.

我們的問題究竟是什么呢?回到起始代碼:

9999999999999999 == 10000000000000000; // true

很明顯,16 個(gè) 9 還遠(yuǎn)遠(yuǎn)小于 308 個(gè) 10. 這個(gè)問題與 MAX_VALUE 沒什么關(guān)系,還得歸屬到尾數(shù) m 只有 52 位上來。

可以用代碼來描述:

var x = 1; // 為了減少運(yùn)算量,初始值可以設(shè)大一點(diǎn),比如 Math.pow(2, 53) - 10
while(x != x + 1) x++;
// x = 9007199254740992 即 2^53

也就是說,當(dāng) x 小于等于 2^53 時(shí),可以確保 x 的精度不會(huì)丟失。當(dāng) x 大于 2^53 時(shí),x 的精度有可能會(huì)丟失。比如:

x 為 2^53 + 1 時(shí),其二進(jìn)制表示為:
10000000000...001 (中間共有 52 個(gè) 0)
用雙精度浮點(diǎn)數(shù)存儲(chǔ)時(shí):
e = 1; m = 10000..00(共 52 個(gè) 0,其中 1 是 hidden bit)
顯然,這和 2^53 的存儲(chǔ)是一樣的。

按照上面的思路可以推出,對(duì)于 2^53 + 2, 其二進(jìn)制為 100000…0010(中間 51 個(gè) 0),也是可以精確存儲(chǔ)的。

規(guī)律:當(dāng) x 大于 2^53 且二進(jìn)制有效位數(shù)大于 53 位時(shí),就會(huì)存在精度丟失。這和小數(shù)的精度丟失本質(zhì)上是一樣的。

hidden bit 可參考:A tutorial about Java double type.

小結(jié)

小數(shù)和大整數(shù)的精度丟失,并不僅僅在 JavaScript 中存在。嚴(yán)格來說,使用了IEEE 754 浮點(diǎn)數(shù)格式來存儲(chǔ)浮點(diǎn)類型的任何編程語言(C/C++/C#/Java 等等)都存在精度丟失問題。在 C#、Java 中,提供了 Decimal、BigDecimal 封裝類來進(jìn)行相應(yīng)的處理,才避開了精度丟失。

注:ECMAScript 規(guī)范中,已有  decimal proposal,但目前尚未被正式采納。

最后考考大家:

Number.MAX_VALUE + 1 == Numer.MAX_VALUE;
Number.MAX_VALUE + 2 == Numer.MAX_VALUE;
...
Number.MAX_VALUE + x == Numer.MAX_VALUE;
Number.MAX_VALUE + x + 1 == Infinity;
...
Number.MAX_VALUE + Number.MAX_VALUE == Infinity;
// 問題:
// 1. x 的值是什么?
// 2. Infinity - Number.MAX_VALUE == x + 1; 是 true 還是 false ?

以上這篇淺談JavaScript中小數(shù)和大整數(shù)的精度丟失就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 給ListBox添加雙擊事件示例代碼

    給ListBox添加雙擊事件示例代碼

    如何給ListBox添加雙擊事件,想必有很多的新手朋友們都不會(huì)吧,下面有個(gè)不錯(cuò)的示例,感興趣的朋友可以參考下
    2013-12-12
  • 一篇文章詳細(xì)講解JavaScript中的this(普通函數(shù)、箭頭函數(shù)、?函數(shù)運(yùn)用)

    一篇文章詳細(xì)講解JavaScript中的this(普通函數(shù)、箭頭函數(shù)、?函數(shù)運(yùn)用)

    這篇文章主要介紹了JavaScript中this關(guān)鍵字的指向規(guī)則,包括全局環(huán)境、函數(shù)、對(duì)象方法、構(gòu)造函數(shù)、事件處理函數(shù)和箭頭函數(shù)中的this指向,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-04-04
  • JavaScript中執(zhí)行上下文和執(zhí)行棧

    JavaScript中執(zhí)行上下文和執(zhí)行棧

    這篇文章主要介紹了JavaScript中執(zhí)行上下文和執(zhí)行棧,執(zhí)行上下文是評(píng)估和執(zhí)行JavaScript代碼的環(huán)境的抽象概念,更多相關(guān)介紹,感興趣的朋友可以參考一下
    2022-09-09
  • 詳解JavaScript如何利用異步解密回調(diào)地獄

    詳解JavaScript如何利用異步解密回調(diào)地獄

    為了更好地處理這些異步操作,JavaScript?引入了異步編程的概念,這篇文章主要來和大家詳細(xì)聊聊JavaScript中異步的相關(guān)應(yīng)用,希望對(duì)大家有所幫助
    2024-02-02
  • JavaScript實(shí)現(xiàn)輪播圖效果代碼實(shí)例

    JavaScript實(shí)現(xiàn)輪播圖效果代碼實(shí)例

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)輪播圖效果代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • js按條件生成隨機(jī)json:randomjson實(shí)現(xiàn)方法

    js按條件生成隨機(jī)json:randomjson實(shí)現(xiàn)方法

    下面小編就為大家?guī)硪黄猨s按條件生成隨機(jī)json:randomjson實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • 防止文件緩存的js代碼

    防止文件緩存的js代碼

    原理其實(shí)就是通過在固定地址后面,加上一個(gè)不同值的日期數(shù)值,以達(dá)到地址不重復(fù)的目的,讓瀏覽器每次都實(shí)時(shí)加載,不從緩存中讀取文件
    2013-01-01
  • 微信小程序圖片上傳組件實(shí)現(xiàn)圖片拖拽排序

    微信小程序圖片上傳組件實(shí)現(xiàn)圖片拖拽排序

    最近在寫小程序過程中遇到一個(gè)拖拽排序需求,上網(wǎng)一頓搜索未果,遂自行實(shí)現(xiàn),下面這篇文章主要給大家介紹了關(guān)于微信小程序圖片上傳組件實(shí)現(xiàn)圖片拖拽排序的相關(guān)資料,需要的朋友可以參考下
    2022-03-03
  • ionic2懶加載配置詳解

    ionic2懶加載配置詳解

    本篇文章主要介紹了ionic2懶加載配置詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09

最新評(píng)論

西丰县| 南江县| 商水县| 阳东县| 政和县| 大厂| 安龙县| 永德县| 枞阳县| 阳城县| 乐至县| 镇沅| 汨罗市| 克拉玛依市| 贵定县| 金寨县| 汕尾市| 田林县| 南木林县| 新密市| 保山市| 冀州市| 柳河县| 陈巴尔虎旗| 靖安县| 崇礼县| 涿州市| 庄河市| 安塞县| 靖西县| 逊克县| 虹口区| 浑源县| 淮阳县| 库尔勒市| 林西县| 历史| 手游| 错那县| 海城市| 灌阳县|