成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JS數值存儲運算原理

開發 前端
JavaScript數值存儲運算原理不知道大家了解不了解,今天我們一起來看一下!

前言

相信大家都看過這些曾經在社區比較火的文章:

  • 0.1 + 0.2 與0.3為什么不相等?
  • 為什么 3.0000000000000002 === 3表達式為true ?
  • 等...

造成這些問題的背后原因都是由于javaScript采用了 IEEE754 標準,全稱 IEEE 二進制浮點數算術標準。所以說這個問題其實不止是會在javaScript中出現,而是「其他遵循 [IEEE 754]標準的語言也會出現這個問題」

并且自己在最近的工作中也遇到了這個問題,由于javaScript精度丟失而造成詭異問題!

javaScript車禍現場

上面三個例子在我們在控制臺里面驗證一遍,是不是瞬間覺得奇怪的知識又增加了?

javaScript這令人窒息的操作是不是讓很多后端人員口吐芬芳了,甚至是很多前端人員都覺得明明都是送分題,卻成了JS的送命題,工作中許多不經意間寫出的bug,往往是由于JS的不按常理出牌。

說了這么多,我們也改變不了這一現狀,那就嘗試去理解它吧~

計算機運算

學過計算機相關同學都知道,我們的計算機底層元算采用的是二進制,而不是我們平常用的十進制!

二進制

「為什么計算機要采用二進制,而不是十進制?」

以下是在知乎上看到的回答,我覺得這個理解是比較到位的。

計算機本身的理論模型,和采用哪個數學上的進制完全無關,十進制也好,五進制也好,二進制也好,進制在數學上都是等價的,并沒有哪個進制擁有其他進制無法實現的計算。

但計算機的實現是個工程問題,需要和真實的物理環境打交道,我們現在是用電路去實現我們的計算機模型,那就需要和物理電路打交道,需要考慮到信號的衰減延遲,電路器件的各種電氣特性,什么電磁波干擾電流擾動,也就是會有失真的情況出現,而要最大程度避免衰減,失真對計算機這個完美世界造成破壞,同時要考慮電路的設計,制作成本,就需要最簡單化的物理實現方案。

電子計算機確實是可以做成十進制的,就像題主說的像燈泡亮度分成十種亮度那樣,但與此同時會出現很多的工程問題,比如對電子器件的精度和穩定性要求很高,電路設計的復雜性提升等等,到頭來還不如就用二進制,在成本和質量上最劃算。

事實上,不但十進制不行,十六進制、八進制、四進制也都比不上二進制。理論上已經證明效率最高的進制是e,離e最近的其實是三進制。但三進制不方便表示,不過也有人研究,前蘇聯就做過三進制計算機,國內也有,但并沒有走出實驗室。效率是一方面,實現成本又是一方面,最終大家還是覺得二進制實現起來最方便。

原碼、反碼、補碼

「為運算方便,機器數有 3 種表示法,即原碼、反碼和補碼」。

原碼

原碼是一種計算機中對數字的二進制定點表示法。「原碼表示法在數值前面增加了一位符號位」。

反碼

正數的反碼和原碼一樣,

負數的反碼就是在原碼的基礎上符號位保持不變,其他位取反。

補碼

正數和 0 的補碼就是該數字本身。

「負數的補碼則是將其對應正數按位取反再加 1」

二進制轉換

「正整數的轉換方法」:除二取余,然后倒序排列,高位補零。

例如21的轉換

商  余
21/2  10  1
10/2  5   0
5/2   2   1
2/2   1   0
1/2   0   1

21的二進制為10101,然后高位補0為00010101

「負整數的轉換方法」:將對應的正整數轉換成二進制后,對二進制取反,然后對結果再加一。

例如-21
先把21轉換成二進制 00010101
逐位取反:11101010
再加1:11101011(補碼)

「小數的轉換方法」:對小數點以后的數乘以2,取整數部分,再取小數部分乘2,以此類推……直到小數部分為0或位數足夠。取整部分按先后順序排列即可。

例如123.4:
0.4*2=0.8 ——————-> 取0
0.8*2=1.6 ——————-> 取1
0.6*2=1.2 ——————-> 取1
0.2*2=0.4 ——————-> 取0
0.4*2=0.8 ——————-> 取0
………… 后面就是循環了
按順序寫出:0.4 = 0.01100110……(0110循環)
整數部分123的二進制是 1111011
則123.4的二進制表示為:1111011.011001100110……

發現了什么?十進制小數轉二進制后大概率出現無限位數!但我們的javaScript采用了「IEEE754」 標準,全稱 「IEEE 二進制浮點數算術標準」。

由于IEEE 754尾數位數限制,會將后面多余的位截掉。

javaScript 與 IEEE 754

“JavaScript 采用 IEEE 754 標準,數值存儲為64位雙精度格式,數值精度最多可以達到 53 個二進制位(1 個隱藏位與 52 個有效位)

圖片

在這個標準下,我們會用1位存儲 S(sign),0 表示正數,1 表示負數。用11位存儲 E(exponent) + bias,對于11位來說,bias 的值是 2^(11-1) - 1,也就是 1023。用52 位存儲 Fraction。

由于javaScript采用的是IEE754標準,所以在進制之間的轉換過程中可能會導致精度丟失,這是造成javaScript運算翻車的罪魁禍首!

破案

0.1+0.2 與 0.3為什么不相等?

0.1.toString(2)
// '0.0001100110011001100110011001100110011001100110011001101'   // 57
// 按 IEEE754 格式  57 - 4 = 52可以精確存儲
0.2.toString(2)
// '0.001100110011001100110011001100110011001100110011001101' // 56
// 按 IEEE754 格式  56 - 3 = 53  會丟棄最后一位數
0.3.toString(2)
// '0.010011001100110011001100110011001100110011001100110011'  // 56
// 按 IEEE754 格式  56 - 2 = 54  會丟棄最后兩位數

/*總結:
存儲0.1沒有誤差, 存儲 0.2丟棄最后一位 1  存儲0.3丟棄最后2位 11,
顯然存儲0.3丟棄的數值>存儲0.2丟棄的數值
經分析 0.1 + 0.2   應該大于 0.3
*/
0.1 + 0.2 > 0.3  // true

為什么 3.0000000000000002 === 3表達式為true ?

手動將 3.0000_0000_0000_0002轉換成二進制浮點數

整數部分為 11?

小數部分0.0000_0000_0000_0002

0.0000_0000_0000_0002.toString(2)

'0.0000000000000000000000000000000000000000000000000000111001101001010110010100101111101100010001001101111'  

注意小數點后面正好有52個0

0.0000_0000_0000_0002.toString(2).length  // 105 105

將 3.0000000000000002 用 IEEE754 格式表示

  1. 符號S: 正數,0
  2. 指數位E:11 = 1.1 * 2^1 (二進制),E = 1023 + 1 = 1024 = 10000000000(二進制)
  3. 尾數位M:0.1.....0

所以該浮點數格式為: 0   1000_0000_000   1...000(一共52個0) 這個數正好是3。

如何解決精度問題?

目前有許多第三方庫可以解決javaScript精度丟失的問題

math.js

math.js是JavaScript和Node.js的一個廣泛的數學庫。支持數字,大數,復數,分數,單位和矩陣等數據類型的運算。

官網:mathjs.org/ GitHub:github.com/josdejong/m…

0.1+0.2 ===0.3實現代碼:

var math = require('mathjs')
console.log(math.add(0.1,0.2))//0.30000000000000004
console.log(math.format((math.add(math.bignumber(0.1),math.bignumber(0.2)))))//'0.3'

decimal.js

為 JavaScript 提供十進制類型的任意精度數值。

官網:mikemcl.github.io/decimal.js/

GitHub:github.com/MikeMcl/dec…

var Decimal = require('decimal.js')
x = new  Decimal(0.1)
y = 0.2
console.log(x.plus(y).toString())//'0.3'

bignumber.js

用于任意精度算術的JavaScript庫。

官網:mikemcl.github.io/bignumber.j…

Github:github.com/MikeMcl/big…

var BigNumber = require("bignumber.js")
x = new BigNumber(0.1)
y = 0.2
console.log(x.plus(y).toString()) //'0.3'


責任編輯:華軒 來源: 前端南玖
相關推薦

2018-03-12 08:53:36

Ceph對象存儲

2012-05-03 15:01:24

數值壓縮

2022-02-09 08:11:50

架構

2022-06-08 07:34:02

持久化數據存儲原理索引存儲格式

2022-10-08 00:21:55

內存芯片RAM

2024-07-05 10:45:09

2024-08-07 09:22:57

2021-07-09 00:24:10

No.jsNode.js原理

2021-01-12 14:46:34

Kubernetes開發存儲

2022-06-02 15:34:45

vmstorage監控

2021-12-13 09:26:31

JS代碼前端

2016-12-16 13:07:30

云存儲運營混合云

2009-10-27 09:12:50

Visual Stud

2021-06-11 18:27:10

LinuxLinux內核

2022-10-27 16:07:24

littlefs存儲結構

2011-11-10 20:31:59

存儲基礎架構智慧的運算

2024-02-26 15:17:20

2022-08-15 14:43:29

深度學習機器視覺機器人

2018-06-13 08:53:39

HadoopHBase存儲

2018-07-27 10:39:13

對象存儲Git
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线免费观看视频你懂的 | 91在线成人 | 久久久www成人免费无遮挡大片 | 激情的网站| 网址黄| 亚洲成人中文字幕 | 亚洲成人精选 | 亚州影院 | 亚洲精品国产电影 | 亚洲在线一区二区三区 | 日韩久久久久 | 北条麻妃一区二区三区在线视频 | 一区二区三区av夏目彩春 | 日韩av在线免费 | 综合久久av | 91在线最新| 国产一二三视频在线观看 | 亚洲精品国产a久久久久久 中文字幕一区二区三区四区五区 | 亚洲一区二区三区免费在线观看 | 成人不卡| 91婷婷韩国欧美一区二区 | 欧美黄色片 | 精品网站999 | 欧美精品一区二区三区蜜桃视频 | 喷水毛片 | 国产一区二区在线播放 | 色婷婷亚洲国产女人的天堂 | 日韩美女一区二区三区在线观看 | 夜夜草 | 韩日精品视频 | 日韩欧美国产精品一区二区三区 | 日韩在线精品强乱中文字幕 | a级免费视频 | 四虎影视一区二区 | 久久国产精品一区二区 | 亚洲视频一区在线观看 | 日本精品视频 | 色视频网站 | 亚洲精品久久久一区二区三区 | h视频免费观看 | 亚洲黄色在线免费观看 |