国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

為什么 JavaScript 中的 0.1 + 0.2 不等于 0.3

這篇具有很好參考價(jià)值的文章主要介紹了為什么 JavaScript 中的 0.1 + 0.2 不等于 0.3。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本文作者為 360 奇舞團(tuán)前端開發(fā)工程師

在使用 JavaScript 處理運(yùn)算時(shí),有時(shí)會(huì)碰到數(shù)字運(yùn)算結(jié)果不符合預(yù)期的情況,比如經(jīng)典的 0.1 + 0.2 不等于 0.3。當(dāng)然這種問題不只存在于 JavaScript,不過編程語言的一些原理大致相通,我以 JavaScript 為例解釋這種問題,并說明前端如何盡可能保證數(shù)字精確。

let a = 0.1,b=0.2,c=0.3
console.log(a + b === c) //false

1. 計(jì)算機(jī)數(shù)字如何存儲(chǔ)

理解類似問題的基礎(chǔ),首先要理解計(jì)算機(jī)數(shù)字的處理方式。計(jì)算機(jī)的一切信息都是二進(jìn)制,數(shù)字也不例外,所有數(shù)字都是一段二進(jìn)制。

在 JavaScript 中存儲(chǔ)數(shù)字的二進(jìn)制有 64 位,即我們常說的 64 位雙精度浮點(diǎn)型數(shù)字。每個(gè)數(shù)字對(duì)應(yīng)的 64 位二進(jìn)制分為三段:符號(hào)位、指數(shù)位、尾數(shù)位。

其中符號(hào)位在六十四位的第一位,0 表示正數(shù),1 表示負(fù)數(shù)。符號(hào)位之后的 11 位是指數(shù)位,決定了數(shù)字的范圍。指數(shù)位之后的 52 位是尾數(shù)位,決定了數(shù)字的精度。

在 JavaScript 中,雙精度浮點(diǎn)型的數(shù)轉(zhuǎn)化成二進(jìn)制的數(shù)保存,讀取時(shí)根據(jù)指數(shù)位和尾數(shù)位的值轉(zhuǎn)化成雙精度浮點(diǎn)數(shù)。

比如說存儲(chǔ) 8.8125 這個(gè)數(shù),它的整數(shù)部分的二進(jìn)制是 1000,小數(shù)部分的二進(jìn)制是 1101。這兩部分連起來是 1000.1101,但是存儲(chǔ)到內(nèi)存中小數(shù)點(diǎn)會(huì)消失,因?yàn)橛?jì)算機(jī)只能存儲(chǔ) 0 和 1。

1000.1101 這個(gè)二進(jìn)制數(shù)用科學(xué)計(jì)數(shù)法表示是 1.0001101 * 2^3,這里的 3 (二進(jìn)制是 0011)即為指數(shù)。

可使用如下代碼查看:

function getBinaryRepresentation(number) {
  const buffer = new ArrayBuffer(8); // 創(chuàng)建一個(gè)包含8字節(jié)的   ArrayBuffer
  const view = new DataView(buffer); // 創(chuàng)建一個(gè)DataView以便訪問內(nèi)存中的數(shù)據(jù)
  view.setFloat64(0, number); // 將浮點(diǎn)數(shù)寫入到內(nèi)存中

  // 讀取內(nèi)存中的字節(jié),并將其轉(zhuǎn)換為二進(jìn)制字符串
  const binaryString = Array.from(new Uint8Array(buffer))
    .map(byte => byte.toString(2).padStart(8, '0'))
    .join('');

  // 將二進(jìn)制字符串分割為符號(hào)位、指數(shù)位和尾數(shù)位
  const signBit = binaryString[0];
  const exponentBits = binaryString.substring(1, 12);
  const mantissaBits = binaryString.substring(12,64);

  return { signBit, exponentBits, mantissaBits };
}

const number = 8.8125; // 要展示的數(shù)字
const { signBit, exponentBits, mantissaBits } = 	getBinaryRepresentation(number);

console.log(`符號(hào)位: ${signBit}`);
console.log(`指數(shù)位: ${exponentBits}`);
console.log(`尾數(shù)位: ${mantissaBits}`);

符號(hào)位: 0
指數(shù)位: 10000000010
尾數(shù)位: 0001101000000000000000000000000000000000000000000000

現(xiàn)在我們很容易判斷符號(hào)位是 0,尾數(shù)位就是科學(xué)計(jì)數(shù)法的小數(shù)部分 0001101。指數(shù)位用來存儲(chǔ)科學(xué)計(jì)數(shù)法的指數(shù),此處為 3。指數(shù)位有正負(fù),11 位指數(shù)位表示的指數(shù)范圍是 -1023~1024,所以指數(shù) 3 的指數(shù)位存儲(chǔ)為 1026(3 + 1023)。

可以判斷 JavaScript 數(shù)值的最大值為 53 位二進(jìn)制的最大值:2^53 -1。

PS:科學(xué)計(jì)數(shù)法中小數(shù)點(diǎn)前的 1 可以省略,因?yàn)檫@一位永遠(yuǎn)是 1。比如 0.5 二進(jìn)制科學(xué)計(jì)數(shù)為 1.00 * 2^-1。

2. 為什么會(huì)產(chǎn)生小數(shù)精度問題

首先補(bǔ)充一下小數(shù)的二進(jìn)制的計(jì)算方法:

十進(jìn)制小數(shù)轉(zhuǎn)為二進(jìn)制與整數(shù)相反,需要每次乘以?2
8.8125
o.8125*2?=?1.625??=>?1
0.625*2?=?1.25??????=>1
0.25*2?=?0.5??????????=>0
0.5*2?=?1?????????????????=>1
小數(shù)部分為?1101
二進(jìn)制小數(shù)轉(zhuǎn)為十進(jìn)制
1*2^-1?+?1*2^-2?+?0*2^-3?+?1*2^-4

在了解數(shù)字的存儲(chǔ)后,很容易理解小數(shù)精度問題,因?yàn)槭M(jìn)制有 Π 這種無限循環(huán)數(shù)字,二進(jìn)制也有循環(huán)數(shù)字。比如讓 0.1 變?yōu)槎M(jìn)制,按照二進(jìn)制轉(zhuǎn)換永遠(yuǎn)會(huì)有余數(shù),所以會(huì)是一個(gè)無限循環(huán)的二進(jìn)制 0.0001 1001 1001 1001...(1100循環(huán))。0.2 也是同理 ?0.0011 0011 0011 0011...(0011循環(huán))。

所以當(dāng)兩個(gè)浮點(diǎn)數(shù)相加時(shí),結(jié)果會(huì)有一些誤差。比如 0.1 + 0.2 ,實(shí)際上是 0.0001 1001 1001...(1001循環(huán)) + 0.0011 0011 0011...(0011循環(huán)),如果截取于第 52 位,就會(huì)得到一個(gè)有誤差的結(jié)果,轉(zhuǎn)為十進(jìn)制為0.30000000000000004,與 0.3 不相等。

3. 前端如何保證小數(shù)準(zhǔn)確

首先出于安全性及準(zhǔn)確性考慮,重要的數(shù)字計(jì)算應(yīng)該交給服務(wù)端負(fù)責(zé),相對(duì)于前端,服務(wù)端有更成熟穩(wěn)定的數(shù)字處理方法,安全性也會(huì)更高。

當(dāng)然前端有時(shí)也需要一些精確的數(shù)字計(jì)算,比如一些動(dòng)畫處理、定時(shí)器處理以及一些條件判斷等。我簡(jiǎn)單列舉幾種方法供大家參考:

  • toFixed 指定小數(shù)位數(shù) 這種方法比較簡(jiǎn)單,不過有個(gè)點(diǎn)要注意,這個(gè)方法是四舍五入,但有時(shí)候看上去并不會(huì),比如 2.55.toFixed(1) 顯示的結(jié)果是 2.5 而不是 2.6。這是因?yàn)?2.55 二進(jìn)制存儲(chǔ)的值并不精確,調(diào)用 2.55.toPrecision(100) 可以看到這個(gè)數(shù)的實(shí)際值是 2.5499..... ,所以截取一位四舍五入是 2.5。再舉一個(gè)例子 (2.449999999999999999).toFixed(1) = 2.5,因?yàn)檫@個(gè)數(shù)與 2.45 的差值小于 Number.EPSILON。

  • 將小數(shù)轉(zhuǎn)為整數(shù)計(jì)算 這個(gè)方法的問題是轉(zhuǎn)換會(huì)增加額外的復(fù)雜度和計(jì)算量,在某些場(chǎng)景下,可能會(huì)導(dǎo)致數(shù)值溢出問題。

  • 第三方庫 精確計(jì)算推薦使用成熟的庫,像 BigNumber.js、decimal.js ,進(jìn)行高精度的浮點(diǎn)數(shù)計(jì)算。原理是把數(shù)字計(jì)算變?yōu)樽址?jì)算。

JavaScript 的計(jì)算比較復(fù)雜,由于沒有細(xì)分?jǐn)?shù)字類型,底層計(jì)算以二進(jìn)制進(jìn)行,存儲(chǔ)值、計(jì)算值都有可能因?yàn)榫葋G失而不準(zhǔn)確,而顯示值可能會(huì)因?yàn)闉g覽器等宿主環(huán)境不同而有差別,所以一定要注意經(jīng)常產(chǎn)生精度丟失的地方。

-?END?-

關(guān)于奇舞團(tuán)

奇舞團(tuán)是 360 集團(tuán)最大的大前端團(tuán)隊(duì),代表集團(tuán)參與 W3C 和 ECMA 會(huì)員(TC39)工作。奇舞團(tuán)非常重視人才培養(yǎng),有工程師、講師、翻譯官、業(yè)務(wù)接口人、團(tuán)隊(duì) Leader 等多種發(fā)展方向供員工選擇,并輔以提供相應(yīng)的技術(shù)力、專業(yè)力、通用力、領(lǐng)導(dǎo)力等培訓(xùn)課程。奇舞團(tuán)以開放和求賢的心態(tài)歡迎各種優(yōu)秀人才關(guān)注和加入奇舞團(tuán)。

為什么 JavaScript 中的 0.1 + 0.2 不等于 0.3,javascript,開發(fā)語言,ecmascript,前端文章來源地址http://www.zghlxwxcb.cn/news/detail-839176.html

到了這里,關(guān)于為什么 JavaScript 中的 0.1 + 0.2 不等于 0.3的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Go 接口:nil接口為什么不等于nil?

    本文主要內(nèi)容:深入了解接口類型的運(yùn)行時(shí)表示層。 目錄 Go 接口:nil接口為什么不等于nil? 一、Go 接口的地位 二、接口的靜態(tài)特性與動(dòng)態(tài)特性 2.1 接口的靜態(tài)特性與動(dòng)態(tài)特性介紹 2.2 “動(dòng)靜皆備”的特性的好處 三、nil error 值 != nil 四、接口類型變量的內(nèi)部表示 第一種:nil 接

    2024年02月05日
    瀏覽(87)
  • 標(biāo)準(zhǔn)化拉普拉斯矩陣特征值范圍為什么小于等于2?(證明)

    譜圖使用標(biāo)準(zhǔn)化拉普拉斯矩陣 L n o r m L^{norm} L n or m 的一個(gè)重要原因就是, L n o r m L^{norm} L n or m 比拉普拉斯矩陣 L L L 穩(wěn)定。很多資料只是簡(jiǎn)單地介紹了 L n o r m L^{norm} L n or m ,在kipfGCN中也只是簡(jiǎn)單地提到 L n o r m L^{norm} L n or m 的特征值不大于2。本文搜集了相關(guān)lecture,并推導(dǎo)

    2024年02月11日
    瀏覽(78)
  • 為什么特征值的重?cái)?shù)大于等于線性無關(guān)特征向量的個(gè)數(shù)

    為什么特征值的重?cái)?shù)大于等于線性無關(guān)特征向量的個(gè)數(shù)

    關(guān)系就是,特征值的重?cái)?shù) ≥ 該特征值的線性無關(guān)向量的個(gè)數(shù) ≥ 1 量化關(guān)系有 特征值的重?cái)?shù),稱為 代數(shù)重?cái)?shù) ,等于Jordan矩陣中特征值為λ的Jordan塊的階數(shù)之和 特征向量的個(gè)數(shù),稱為 幾何重?cái)?shù) ,等于Jordan矩陣中特征值為λ的Jordan塊的個(gè)數(shù) 證明 先說結(jié)論 每個(gè)矩陣 等價(jià) 于一個(gè)

    2024年02月11日
    瀏覽(89)
  • C++ 為什么double類型不能直接判斷等于0 兩個(gè)double類型怎么判斷相等

    精度丟失, 十進(jìn)制小數(shù)部分在轉(zhuǎn)換成2進(jìn)制的時(shí)候經(jīng)常會(huì)出現(xiàn)無限位的二進(jìn)制小數(shù),計(jì)算機(jī)存儲(chǔ)小數(shù)有長度限制,所以會(huì)進(jìn)行截取部分小數(shù)進(jìn)行存儲(chǔ),計(jì)算機(jī)只能存儲(chǔ)大概的值,而不是精確的值 。 例如: 判斷一個(gè)單精度浮點(diǎn)數(shù):則是 if( abs(f) = 1e-6); 要判斷一個(gè)雙精度浮點(diǎn)數(shù)

    2024年02月12日
    瀏覽(104)
  • TypeScript:為什么JavaScript需要類型檢查?

    JavaScript是當(dāng)今最為流行的編程語言之一。它是一種高級(jí)的、解釋性的編程語言,用于Web應(yīng)用程序的開發(fā)。然而,JavaScript的靈活性也是它的弱點(diǎn)之一。JavaScript中的變量、函數(shù)、類等都是動(dòng)態(tài)類型,這意味著它們的類型可以在運(yùn)行時(shí)發(fā)生變化。雖然這種靈活性為JavaScript開發(fā)人員

    2024年02月04日
    瀏覽(22)
  • 為什么要去了解javascript的底層?

    JavaScript的基本數(shù)據(jù)類型包括:數(shù)字、字符串、布爾值、null、undefined。其中,數(shù)字類型可以是整數(shù)或浮點(diǎn)數(shù),字符串類型用單引號(hào)或雙引號(hào)表示,布爾值只有true和false兩個(gè)取值,null表示一個(gè)空值,undefined表示一個(gè)未定義的值。 在JavaScript底層實(shí)現(xiàn)中,每種數(shù)據(jù)類型都有相應(yīng)的

    2024年02月01日
    瀏覽(21)
  • JavaScript——為什么靜態(tài)方法不能調(diào)用非靜態(tài)方法

    JavaScript——為什么靜態(tài)方法不能調(diào)用非靜態(tài)方法

    個(gè)人簡(jiǎn)介 ?? 個(gè)人主頁: 前端雜貨鋪 ???♂? 學(xué)習(xí)方向: 主攻前端方向,正逐漸往全干發(fā)展 ?? 個(gè)人狀態(tài): 研發(fā)工程師,現(xiàn)效力于中國工業(yè)軟件事業(yè) ?? 人生格言: 積跬步至千里,積小流成江海 ?? 推薦學(xué)習(xí):??前端面試寶典 ??Vue2 ??Vue3 ??Vue2/3項(xiàng)目實(shí)戰(zhàn) ??Node.js??

    2024年02月11日
    瀏覽(26)
  • Golang 中的 slice 為什么是并發(fā)不安全的?

    Golang 中的 slice 為什么是并發(fā)不安全的?

    ??在Go語言中,slice是并發(fā)不安全的,主要有以下兩個(gè)原因:數(shù)據(jù)競(jìng)爭(zhēng)、內(nèi)存重分配。 ??數(shù)據(jù)競(jìng)爭(zhēng):slice底層的結(jié)構(gòu)體包含一個(gè)指向底層數(shù)組的指針和該數(shù)組的長度,當(dāng)多個(gè)協(xié)程并發(fā)訪問同一個(gè)slice時(shí),有可能會(huì)出現(xiàn)數(shù)據(jù)競(jìng)爭(zhēng)的問題。例如,一個(gè)協(xié)程在修改slice的長度,而

    2024年02月05日
    瀏覽(28)
  • Golang 中的 map 為什么是并發(fā)不安全的?

    Golang 中的 map 為什么是并發(fā)不安全的?

    ??golang 中的 map 是并發(fā)不安全的,多個(gè) go 協(xié)程同時(shí)對(duì)同一個(gè) map 進(jìn)行讀寫操作時(shí),會(huì)導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng)(data race)問題,程序會(huì) panic。 ??如果一個(gè)協(xié)程正在寫入 map,而另一個(gè)協(xié)程正在讀取或?qū)懭?map,那么就有可能出現(xiàn)一些未定義的行為,例如:讀取到的值可能是過期的、不

    2024年02月05日
    瀏覽(25)
  • Java中的實(shí)體類為什么要 implements Serializable?

    Java中的實(shí)體類為什么要 implements Serializable?

    1. 序列化和反序列化 首先來解釋一下什么是序列化和反序列化: 序列化 :把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化。 反序列化 :把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列化。 在 Java 和其他語言進(jìn)行通信的時(shí)候,需要將對(duì)象轉(zhuǎn)化成一種通用的格式例如Json( 轉(zhuǎn)換

    2023年04月20日
    瀏覽(11)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包