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

JavaScript中小數(shù)點(diǎn)精度丟失的原因以及解決方法

 更新時(shí)間:2023年10月18日 09:10:49   作者:你臉上長(zhǎng)麻子  
計(jì)算機(jī)再大的內(nèi)存它也存不下,所以不能存儲(chǔ)一個(gè)相對(duì)于數(shù)學(xué)來(lái)說(shuō)的值,只能存儲(chǔ)一個(gè)近似值,所以當(dāng)計(jì)算機(jī)存儲(chǔ)后再取出來(lái)用時(shí)就會(huì)出現(xiàn)精度問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于JavaScript中小數(shù)點(diǎn)精度丟失的原因以及解決方法,需要的朋友可以參考下

一、為什么會(huì)出現(xiàn)計(jì)算精度丟失的問(wèn)題?

JavaScript中存在小數(shù)點(diǎn)精度丟失的問(wèn)題是由于其使用的浮點(diǎn)數(shù)表示方式。JavaScript采用的是雙精度浮點(diǎn)數(shù)表示法,也稱(chēng)為IEEE 754標(biāo)準(zhǔn),它使用64位來(lái)表示一個(gè)數(shù)字,其中52位用于表示有效數(shù)字,而其他位用于表示符號(hào)、指數(shù)和特殊情況。

由于使用有限的位數(shù)來(lái)表示無(wú)限的小數(shù),JavaScript無(wú)法準(zhǔn)確地表示某些小數(shù)。其中一個(gè)典型的示例是0.1,它在二進(jìn)制中是一個(gè)無(wú)限循環(huán)的小數(shù)。當(dāng)我們將0.1這樣的小數(shù)轉(zhuǎn)換為二進(jìn)制進(jìn)行存儲(chǔ)時(shí),存在近似表示的誤差,因此在進(jìn)行計(jì)算時(shí)會(huì)出現(xiàn)精度丟失的問(wèn)題。
例如,執(zhí)行以下計(jì)算:

0.1 + 0.2

預(yù)期的結(jié)果應(yīng)該是0.3,但在JavaScript中實(shí)際得到的結(jié)果是0.30000000000000004。這是因?yàn)?.1和0.2無(wú)法以精確的二進(jìn)制形式表示,導(dǎo)致小數(shù)點(diǎn)精度丟失。

這種精度丟失是浮點(diǎn)數(shù)表示法的固有特性,并不僅限于JavaScript,其他編程語(yǔ)言也可能面臨類(lèi)似的問(wèn)題。因此,在進(jìn)行精確計(jì)算時(shí),特別是涉及到貨幣、金融等方面的計(jì)算,應(yīng)使用其它精確計(jì)算的方法,例如使用整數(shù)進(jìn)行運(yùn)算或使用專(zhuān)門(mén)的精確計(jì)算庫(kù)。

總而言之,小數(shù)點(diǎn)精度丟失的問(wèn)題是由于JavaScript使用的浮點(diǎn)數(shù)表示法的特性所致,需要在開(kāi)發(fā)中注意,并考慮使用其他方法或工具來(lái)解決精度問(wèn)題。

二、代碼示例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        var floatObj = function () {
            // 判斷傳入的值-是否為整數(shù)
            function isInteger(obj) {
                return Math.floor(obj) === obj
            }
            // 將一個(gè)浮點(diǎn)數(shù)轉(zhuǎn)成整數(shù),返回整數(shù)和倍數(shù)。如 3.14 >> 314,倍數(shù)是 100
            // @param floatNum { number } 小數(shù)
            // @return { object }
            // { times: 100, num: 314 }
            // 用于返回整數(shù)和倍數(shù)
            function toInteger(floatNum) {
                // 聲明一個(gè)對(duì)象用來(lái)保存倍數(shù)和整數(shù)
                var ret = { times: 1, num: 0 }
                // 第一種情況:是整數(shù)
                if (isInteger(floatNum)) {
                    // 把整數(shù)給 ret中的   num
                    ret.num = floatNum
                    return ret //  最后返回 ret
                }
                // 第二種情況-不是整數(shù),
                var strfi = floatNum + ''  // 轉(zhuǎn)為字符串  "0.1"
                var dotPos = strfi.indexOf('.')  // 查詢(xún)小數(shù)點(diǎn)
                var len = strfi.substr(dotPos + 1).length; //  獲取小數(shù)點(diǎn)后的長(zhǎng)度
                var times = Math.pow(10, len)  // 放大多少倍
                var intNum = Number(floatNum.toString().replace('.', ''))  // 返回 轉(zhuǎn)為字符串  截取掉小數(shù)點(diǎn)  最后轉(zhuǎn)為數(shù)字(整數(shù))
                // 把獲取到的倍數(shù)和整數(shù)存入對(duì)象中
                ret.times = times
                ret.num = intNum
                return ret
            }
            // 核心方法,實(shí)現(xiàn)加減乘除運(yùn)算,確保不丟失精度
            // 思路:把小數(shù)放大為整數(shù)(乘),進(jìn)行算術(shù)運(yùn)算,再縮小為小數(shù)(除)
            // @param a { number } 運(yùn)算數(shù)1
            // @param b { number } 運(yùn)算數(shù)2
            // @param digits { number } 精度,保留的小數(shù)點(diǎn)數(shù),比如 2, 即保留為兩位小數(shù)
            // @param op { string } 運(yùn)算類(lèi)型,有加減乘除(add / subtract / multiply / divide)
            function operation(a, b, digits, op) {
                // 獲取倍數(shù)和整數(shù)的對(duì)象
                var o1 = toInteger(a)
                var o2 = toInteger(b)
                // 提取整數(shù)
                var n1 = o1.num
                var n2 = o2.num
                // 提取倍數(shù)
                var t1 = o1.times
                var t2 = o2.times
                // 獲取最大倍數(shù)
                var max = t1 > t2 ? t1 : t2
                var result = null  //
                switch (op) {
                    case 'add':
                        if (t1 === t2) { // 兩個(gè)小數(shù)位數(shù)相同
                            result = n1 + n2    //  
                        } else if (t1 > t2) { // o1 小數(shù)位 大于 o2
                            result = n1 + n2 * (t1 / t2)
                        } else { // o1 小數(shù)位 小于 o2
                            result = n1 * (t2 / t1) + n2
                        }
                        return result / max
                    case 'subtract':
                        if (t1 === t2) {
                            result = n1 - n2
                        } else if (t1 > t2) {
                            result = n1 - n2 * (t1 / t2)
                        } else {
                            result = n1 * (t2 / t1) - n2
                        }
                        return result / max
                    case 'multiply':
                        result = (n1 * n2) / (t1 * t2)
                        return result
                    case 'divide':
                        result = (n1 / n2) * (t2 / t1)
                        return result
                }
            }
            // 加減乘除的四個(gè)接口
            function add(a, b, digits) {
                return operation(a, b, digits, 'add')
            }
            function subtract(a, b, digits) {
                return operation(a, b, digits, 'subtract')
            }
            function multiply(a, b, digits) {
                return operation(a, b, digits, 'multiply')
            }
            function divide(a, b, digits) {
                return operation(a, b, digits, 'divide')
            }
            return {
                add: add,
                subtract: subtract,
                multiply: multiply,
                divide: divide
            }
        }();
        // console.log(floatObj.add(0.5, 0.2))
        console.log(floatObj.add(0.12, 0.3))
    </script>
</head>
<body>
</body>
</html>

三、解決思路

解決方法:

1.首先封裝一個(gè)函數(shù),這個(gè)函數(shù)是用來(lái)判斷單價(jià)是否為一個(gè)整數(shù)。

2.然后在封裝第二個(gè)函數(shù),這個(gè)函數(shù)的作用是返回整數(shù)和倍數(shù)的。

同時(shí)聲明一個(gè)對(duì)象ret來(lái)保存這個(gè)倍數(shù)和整數(shù),

第一種情況就是單價(jià)傳過(guò)來(lái)時(shí)就是整數(shù),那么他的倍數(shù)也就為1, 所以我們可以直接存儲(chǔ)到聲明的對(duì)象中

第二種情況就是當(dāng)單價(jià)傳過(guò)來(lái)時(shí)是浮點(diǎn)數(shù),這時(shí)候我們就要做處理,

(1)、將傳遞過(guò)來(lái)的參數(shù)轉(zhuǎn)為字符串(隱式轉(zhuǎn)換),  

(2)、使用indexOf找到小數(shù)點(diǎn)'.',

(3)、使用substr字符串方法截取小數(shù)點(diǎn)后的長(zhǎng)度length,

(4)、聲明一個(gè)為倍數(shù)的變量Time,同時(shí)使用Math.pow(10, 上一步截取的長(zhǎng)度),   這個(gè)time就是倍數(shù),小數(shù)點(diǎn)后每多一位就會(huì)為10×長(zhǎng)度的次方,再將浮點(diǎn)數(shù)轉(zhuǎn)換為整數(shù)(tostring轉(zhuǎn)為字符, 使用replace將小數(shù)點(diǎn)替換為空,再用Number將字符串轉(zhuǎn)為數(shù)字)

最后將獲取到的倍數(shù)和整數(shù)存入對(duì)象中即可

3.最后實(shí)現(xiàn)加減乘除運(yùn)算,確保不丟失精度         

主要思路:把小數(shù)放大為整數(shù)(乘),進(jìn)行算術(shù)運(yùn)算,再縮小為小數(shù)(除)

再次封裝一個(gè)為實(shí)現(xiàn)運(yùn)算的函數(shù)這個(gè)函數(shù)接受三個(gè)參數(shù)(運(yùn)算數(shù)1,運(yùn)算數(shù)2, '加減乘除四個(gè)方法的函數(shù)'),

聲明n1, n2, 分別為單價(jià)1, 單價(jià)2,

聲明t1, t2.為單價(jià)1的倍數(shù)和單價(jià)2的倍數(shù)

再獲取最大倍數(shù)max(使用三元運(yùn)算符),

使用switch判斷條件就是('加減乘除四個(gè)方法的函數(shù)')搭配Case判斷

加法: 三種狀況

1.t1和t2相同的情況下,就是兩個(gè)小數(shù)的位數(shù)相同情況下直接返回n1 + n2 就是整數(shù)相加

2.t1大于t2的情況下 第一個(gè)小數(shù)位數(shù)大于第二位返回, n1 + n2 * (t1 / t2):

3.t1小于t2的情況下 第一個(gè)小數(shù)位數(shù)小于第二位返回, n1 * (t2 / t1) + n2

最后無(wú)論走得是哪一種情況結(jié)果都要除以max(最大倍數(shù))

減法: 三種狀況

1.t1和t2相同的情況下,就是兩個(gè)小數(shù)的位數(shù)相同情況下直接返回n1 - n2 就是整數(shù)相減

2.t1大于t2的情況下 第一個(gè)小數(shù)位數(shù)大于第二位返回, n1 - n2 * (t1 / t2)

3.t1小于t2的情況下 第一個(gè)小數(shù)位數(shù)小于第二位返回, n1 * (t2 / t1) - n2

最后無(wú)論走得是哪一種情況結(jié)果都要除以max(最大倍數(shù))

乘法: 判斷狀態(tài)時(shí)候結(jié)果的是(n1 × n2)/ (t1 × t2)

除法: 判斷狀態(tài)時(shí)候結(jié)果的是(n1 × n2)/ (t1 × t2)

--- 最后進(jìn)行加減乘除進(jìn)行封裝,return這四個(gè)函數(shù)-- -

四、解決的問(wèn)題

在 JavaScript 中處理小數(shù)點(diǎn)精度可以帶來(lái)以下幾個(gè)好處:

避免精度丟失:JavaScript 使用 IEEE 754 浮點(diǎn)數(shù)標(biāo)準(zhǔn)來(lái)表示數(shù)字,但由于浮點(diǎn)數(shù)存儲(chǔ)的是二進(jìn)制近似值,會(huì)導(dǎo)致一些小數(shù)無(wú)法被準(zhǔn)確表示,從而造成精度丟失。通過(guò)處理小數(shù)點(diǎn)精度,可以減少這種精度丟失的情況,確保計(jì)算結(jié)果的準(zhǔn)確性。

精確計(jì)算金融數(shù)據(jù):在金融領(lǐng)域,小數(shù)點(diǎn)精度非常重要。處理貨幣金額、計(jì)算利率和利息等都需要保持精確的小數(shù)點(diǎn)計(jì)算,以避免數(shù)據(jù)錯(cuò)誤和損失。

避免舍入誤差:當(dāng)進(jìn)行多個(gè)浮點(diǎn)數(shù)計(jì)算時(shí),由于每次計(jì)算都可能存在一定的舍入誤差,累積計(jì)算結(jié)果可能會(huì)與預(yù)期的結(jié)果有所偏差。通過(guò)處理小數(shù)點(diǎn)精度,可以減少舍入誤差的影響,提高計(jì)算的準(zhǔn)確性。

增強(qiáng)數(shù)據(jù)可視化:在圖表和可視化數(shù)據(jù)中,小數(shù)點(diǎn)精度可以提供更精確的數(shù)據(jù)展示。例如,在繪制股票價(jià)格曲線或者科學(xué)實(shí)驗(yàn)數(shù)據(jù)時(shí),小數(shù)點(diǎn)精度可以使得數(shù)據(jù)更加準(zhǔn)確和可信。

總的來(lái)說(shuō),處理小數(shù)點(diǎn)精度可以確保計(jì)算結(jié)果的準(zhǔn)確性,尤其在對(duì)于金融數(shù)據(jù)和需要高精度計(jì)算的場(chǎng)景下,這種處理是非常重要的。

五、二進(jìn)制存儲(chǔ)原理

在JS中不區(qū)分整數(shù)和小數(shù),因?yàn)镴S中天生浮點(diǎn)數(shù)(雙精度),在計(jì)算機(jī)存儲(chǔ)中,雙精度的實(shí)際存儲(chǔ)位數(shù)是52位,由于二進(jìn)制中只有 0 和 1,但52位有時(shí)并不能準(zhǔn)確的表達(dá)小數(shù)點(diǎn)后面的數(shù)字,在十進(jìn)制中有四舍五入,在二進(jìn)制中存在0舍1入,所以當(dāng)52位無(wú)法準(zhǔn)確的表達(dá)出一個(gè)小數(shù)時(shí),就會(huì)產(chǎn)生補(bǔ)位動(dòng)作,數(shù)值偏差就在這時(shí)產(chǎn)生了,這是造成計(jì)算精度問(wèn)題的原因。

總結(jié)

到此這篇關(guān)于JavaScript中小數(shù)點(diǎn)精度丟失的原因以及解決方法的文章就介紹到這了,更多相關(guān)JS小數(shù)點(diǎn)精度丟失內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • js打開(kāi)word文檔預(yù)覽操作示例【不是下載】

    js打開(kāi)word文檔預(yù)覽操作示例【不是下載】

    這篇文章主要介紹了js打開(kāi)word文檔預(yù)覽操作,結(jié)合實(shí)例形式分析了兩種javascript打開(kāi)word文檔在線預(yù)覽相關(guān)操作技巧,需要的朋友可以參考下
    2019-05-05
  • selenium 反爬蟲(chóng)之跳過(guò)淘寶滑塊驗(yàn)證功能的實(shí)現(xiàn)代碼

    selenium 反爬蟲(chóng)之跳過(guò)淘寶滑塊驗(yàn)證功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了selenium 反爬蟲(chóng)之跳過(guò)淘寶滑塊驗(yàn)證功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 微信小程序通過(guò)websocket實(shí)時(shí)語(yǔ)音識(shí)別的實(shí)現(xiàn)代碼

    微信小程序通過(guò)websocket實(shí)時(shí)語(yǔ)音識(shí)別的實(shí)現(xiàn)代碼

    這篇文章主要介紹了微信小程序通過(guò)websocket實(shí)時(shí)語(yǔ)音識(shí)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • D3.js實(shí)現(xiàn)柱狀圖的方法詳解

    D3.js實(shí)現(xiàn)柱狀圖的方法詳解

    相信大家都知道數(shù)據(jù)可視化就是借助圖形化的手段把生硬的數(shù)據(jù)生動(dòng)化,以此來(lái)展示出數(shù)據(jù)想要表達(dá)的信息,而圖表是最通常的一種數(shù)據(jù)可視化手段??扇孔约杭兪謩?dòng)編寫(xiě)各種圖表實(shí)在是讓人頭疼,各種計(jì)算各種煩?,F(xiàn)在就為大家介紹如何用D3.js來(lái)實(shí)現(xiàn)柱狀圖。
    2016-09-09
  • JS兩種類(lèi)型的表單提交方法實(shí)例分析

    JS兩種類(lèi)型的表單提交方法實(shí)例分析

    這篇文章主要介紹了JS兩種類(lèi)型的表單提交方法,結(jié)合實(shí)例形式分析了2種常用的表單提交驗(yàn)證的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • Bootstrap入門(mén)書(shū)籍之(一)排版

    Bootstrap入門(mén)書(shū)籍之(一)排版

    這篇文章主要介紹了Bootstrap入門(mén)書(shū)籍之(一)排版的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • 淺談redux, koa, express 中間件實(shí)現(xiàn)對(duì)比解析

    淺談redux, koa, express 中間件實(shí)現(xiàn)對(duì)比解析

    這篇文章主要介紹了淺談redux, koa, express 中間件實(shí)現(xiàn)對(duì)比解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 網(wǎng)頁(yè)中右鍵功能的實(shí)現(xiàn)方法之contextMenu的使用

    網(wǎng)頁(yè)中右鍵功能的實(shí)現(xiàn)方法之contextMenu的使用

    本文介紹一種網(wǎng)頁(yè)中實(shí)現(xiàn)右鍵功能的方案–contextMenu,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2017-02-02
  • 工作中常用js功能匯總

    工作中常用js功能匯總

    這篇文章主要介紹了一些工作中常用js功能的匯總,幫助大家提高工作效率,加深對(duì)js的理解,感興趣的朋友可以了解下
    2020-11-11
  • 微信小程序自定義組件和通信的方法

    微信小程序自定義組件和通信的方法

    開(kāi)發(fā)中常見(jiàn)的組件主要分為公共組件和頁(yè)面組件兩種,因此注冊(cè)組件的方式也分為兩種全局注冊(cè)和局部注冊(cè),本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-06-06

最新評(píng)論

法库县| 浑源县| 宁德市| 平乐县| 灵丘县| 赤水市| 隆子县| 安福县| 高密市| 浦江县| 阿拉善右旗| 扶余县| 新安县| 双鸭山市| 郧西县| 筠连县| 姚安县| 茂名市| 河源市| 雷州市| 凌云县| 泰安市| 龙门县| 山阴县| 湘乡市| 泗阳县| 巫溪县| 商丘市| 正蓝旗| 陆丰市| 格尔木市| 新干县| 环江| 会泽县| 五莲县| 民县| 丹巴县| 称多县| 绥滨县| 平武县| 清丰县|