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

JS數(shù)值存儲運算原理

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

前言

相信大家都看過這些曾經(jīng)在社區(qū)比較火的文章:

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

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

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

javaScript車禍現(xiàn)場

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

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

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

計算機運算

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

二進制

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

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

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

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

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

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

原碼、反碼、補碼

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

原碼

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

反碼

正數(shù)的反碼和原碼一樣,

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

補碼

正數(shù)和 0 的補碼就是該數(shù)字本身。

「負數(shù)的補碼則是將其對應(yīng)正數(shù)按位取反再加 1」

二進制轉(zhuǎn)換

「正整數(shù)的轉(zhuǎn)換方法」:除二取余,然后倒序排列,高位補零。

例如21的轉(zhuǎn)換

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

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

「負整數(shù)的轉(zhuǎn)換方法」:將對應(yīng)的正整數(shù)轉(zhuǎn)換成二進制后,對二進制取反,然后對結(jié)果再加一。

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

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

例如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
………… 后面就是循環(huán)了
按順序?qū)懗觯?.4 = 0.01100110……(0110循環(huán))
整數(shù)部分123的二進制是 1111011
則123.4的二進制表示為:1111011.011001100110……

發(fā)現(xiàn)了什么?十進制小數(shù)轉(zhuǎn)二進制后大概率出現(xiàn)無限位數(shù)!但我們的javaScript采用了「IEEE754」 標準,全稱 「IEEE 二進制浮點數(shù)算術(shù)標準」。

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

javaScript 與 IEEE 754

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

圖片

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

由于javaScript采用的是IEE754標準,所以在進制之間的轉(zhuǎn)換過程中可能會導(dǎo)致精度丟失,這是造成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  會丟棄最后一位數(shù)
0.3.toString(2)
// '0.010011001100110011001100110011001100110011001100110011'  // 56
// 按 IEEE754 格式  56 - 2 = 54  會丟棄最后兩位數(shù)

/*總結(jié):
存儲0.1沒有誤差, 存儲 0.2丟棄最后一位 1  存儲0.3丟棄最后2位 11,
顯然存儲0.3丟棄的數(shù)值>存儲0.2丟棄的數(shù)值
經(jīng)分析 0.1 + 0.2   應(yīng)該大于 0.3
*/
0.1 + 0.2 > 0.3  // true

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

手動將 3.0000_0000_0000_0002轉(zhuǎn)換成二進制浮點數(shù)

整數(shù)部分為 11?

小數(shù)部分0.0000_0000_0000_0002

0.0000_0000_0000_0002.toString(2)

'0.0000000000000000000000000000000000000000000000000000111001101001010110010100101111101100010001001101111'  

注意小數(shù)點后面正好有52個0

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

將 3.0000000000000002 用 IEEE754 格式表示

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

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

如何解決精度問題?

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

math.js

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

官網(wǎng):mathjs.org/ GitHub:github.com/josdejong/m…

0.1+0.2 ===0.3實現(xiàn)代碼:

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 提供十進制類型的任意精度數(shù)值。

官網(wǎng):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

用于任意精度算術(shù)的JavaScript庫。

官網(wǎng):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'


責(zé)任編輯:華軒 來源: 前端南玖
相關(guān)推薦

2018-03-12 08:53:36

Ceph對象存儲

2012-05-03 15:01:24

數(shù)值壓縮

2022-02-09 08:11:50

架構(gòu)

2022-06-08 07:34:02

持久化數(shù)據(jù)存儲原理索引存儲格式

2022-10-08 00:21:55

內(nèi)存芯片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開發(fā)存儲

2022-06-02 15:34:45

vmstorage監(jiān)控

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內(nèi)核

2022-10-27 16:07:24

littlefs存儲結(jié)構(gòu)

2011-11-10 20:31:59

存儲基礎(chǔ)架構(gòu)智慧的運算

2022-08-15 14:43:29

深度學(xué)習(xí)機器視覺機器人

2024-02-26 15:17:20

2023-11-22 08:35:34

存儲引擎bitcask

2018-06-13 08:53:39

HadoopHBase存儲
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 欧美 日韩 亚洲91麻豆精品 | 九色av| 秋霞电影一区二区 | 日韩成人精品在线 | 亚洲人在线观看视频 | 污书屋| 91福利在线导航 | 精品国产欧美一区二区三区不卡 | 欧美在线a| 国产精品小视频在线观看 | 午夜影院操| 亚洲欧美一区二区三区视频 | 国产精品国产精品 | 亚洲成人高清 | 国产国产精品久久久久 | 天天干天天玩天天操 | 欧美xxxⅹ性欧美大片 | 久久久久久久久久久久久久av | 欧美日韩精品久久久免费观看 | 久久999 | 欧美日本韩国一区二区三区 | 日本不卡一区 | 一区二区在线不卡 | 黄色香蕉视频在线观看 | 国产综合av | 91文字幕巨乱亚洲香蕉 | 一级毛片免费 | 亚洲一区在线播放 | 视频三区 | 黄视频网址 | 亚洲电影一区二区三区 | 人操人人 | 免费看一级毛片 | 亚洲人成网亚洲欧洲无码 | 国产亚洲欧美在线 | 日韩精品在线网站 | 日日日色 | 91中文字幕在线观看 | 一级黄色片毛片 | 成人免费观看男女羞羞视频 | 精品亚洲一区二区 |