摘要:但由于十進(jìn)制小數(shù)并不總能用二進(jìn)制小數(shù)精確表示,在進(jìn)行小數(shù)運(yùn)算時(shí),經(jīng)常會(huì)出現(xiàn)莫明其妙的誤差,比如之類的。它唯一能解決的問(wèn)題就是避免十進(jìn)制小數(shù)和二進(jìn)制小數(shù)之間的轉(zhuǎn)換誤差它不能提高運(yùn)算的精度有效數(shù)字,也不能擴(kuò)大數(shù)字的表示范圍。
以前的舊文,貌似還是挺有用的,在這里記一下避免丟失:
基于Web的應(yīng)用程序,經(jīng)常需要在頁(yè)面中作些簡(jiǎn)單的計(jì)算,用作數(shù)據(jù)提交前的驗(yàn)證,或者給用戶提供更友好的信息。但由于十進(jìn)制小數(shù)并不總能用二進(jìn)制小數(shù)精確表示,在進(jìn)行小數(shù)運(yùn)算時(shí),經(jīng)常會(huì)出現(xiàn)“莫明其妙”的誤差,比如“33*2.46=81.179999999999999”之類的。如果要在頁(yè)面上顯示計(jì)算結(jié)果,特別是當(dāng)這個(gè)結(jié)果表示金額的時(shí)候,誤差通常是不可容忍的。
網(wǎng)上有人說(shuō)Javasript不能做精確運(yùn)算,所以會(huì)出現(xiàn)誤差云云。這當(dāng)然是不對(duì)的,這種情況應(yīng)該是由計(jì)算機(jī)二進(jìn)制表示的本質(zhì)決定的。應(yīng)該說(shuō),Javascript的表現(xiàn)其實(shí)還好一些,因?yàn)樵跀?shù)字進(jìn)行運(yùn)算之前,我們總是可以得到它的精確表示(字符串)。
解決問(wèn)題的基本思路就是犧牲速度換精度,逐位進(jìn)行運(yùn)算,并且自己在程序邏輯中實(shí)現(xiàn)進(jìn)位。為此,Java提供了BigDecimal類。而在Javascript中,我們就沒(méi)這么幸運(yùn)了,沒(méi)有現(xiàn)成的類庫(kù)可供使用??赡苁侵朴喴?guī)范的人也認(rèn)為沒(méi)必要使用JS來(lái)做“科學(xué)計(jì)算”吧。
我以前做的項(xiàng)目中,經(jīng)常會(huì)碰到計(jì)算金額總價(jià)、合計(jì)、總計(jì)之類的“商業(yè)計(jì)算”,對(duì)精確小數(shù)運(yùn)算的需求還是比較迫切的,所以自己開(kāi)發(fā)了一個(gè)小數(shù)運(yùn)算的“類”。實(shí)現(xiàn)這個(gè)類的時(shí)候,使用了投機(jī)取巧的辦法:把小數(shù)轉(zhuǎn)換為整數(shù),運(yùn)算完成后,再轉(zhuǎn)換回去。它唯一能解決的問(wèn)題就是:避免十進(jìn)制小數(shù)和二進(jìn)制小數(shù)之間的轉(zhuǎn)換誤差;它不能提高運(yùn)算的精度(有效數(shù)字),也不能擴(kuò)大數(shù)字的表示范圍。
使用方法如下:
//使用數(shù)字的literal表示,創(chuàng)建一個(gè)Decimal對(duì)象 var d1 = new Decimal(3.68); //調(diào)用該對(duì)象的四則運(yùn)算方法,得到一個(gè)新的Decimal對(duì)象 var res=d1.add(2.25); //調(diào)用該對(duì)象的valueOf方法,得到數(shù)值 alert( res.valueOf() ); //顯示 5.93 //或者調(diào)用該對(duì)象的toString方法,得到數(shù)值的字符串表示 alert( res.toString() ); //顯示 5.93 //可用的運(yùn)算方法對(duì)應(yīng)四則運(yùn)算的+、-、×、÷ var d1 = new Decimal(3.68); var res=d1.add(2.25); assertEquals("3.68+2.25", "5.93", res.toString()); var d1 = new Decimal(3.68); var res=d1.minus(2.25); assertEquals("3.68-2.25", "1.43", res.toString()); var d1 = new Decimal(2.22); var res=d1.multiply(3.33); assertEquals("2.22*3.33", 7.3926, res.valueOf()); var d1 = new Decimal(6.66); var res=d1.divide(2.22); assertEquals("6.66/2.22", 3, res.valueOf());
源碼在這里下載:https://pan.baidu.com/s/1i4Gugqp
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/81665.html
摘要:使用,保證精度的同時(shí),能精準(zhǔn)的進(jìn)行四舍六入計(jì)算。類精確的數(shù)學(xué)運(yùn)算使用來(lái)實(shí)現(xiàn)精準(zhǔn)度因?yàn)榫鹊脑驑?gòu)造方法的結(jié)果有一定的不可預(yù)知性,例如因此建議使用。算法規(guī)則四舍六入五考慮,五后非零就進(jìn)一,五后皆零看奇偶,五前為偶應(yīng)舍去,五前為奇要進(jìn)一。 四舍六入計(jì)算 算法規(guī)則: 四舍六入五考慮, 五后非零就進(jìn)一, 五后皆零看奇偶, 五前為偶應(yīng)舍去, 五前為奇要進(jìn)一。 使用BigDecimal,保證精度的...
摘要:也就是說(shuō)不僅是會(huì)產(chǎn)生這種問(wèn)題,只要是采用的浮點(diǎn)數(shù)編碼方式來(lái)表示浮點(diǎn)數(shù)時(shí),則會(huì)產(chǎn)生這類問(wèn)題。到這里我們都理解只要采取的浮點(diǎn)數(shù)編碼的語(yǔ)言均會(huì)出現(xiàn)上述問(wèn)題,只是它們的標(biāo)準(zhǔn)類庫(kù)已經(jīng)為我們提供了解決方案而已。 Brief 一天有個(gè)朋友問(wèn)我JS中計(jì)算0.7 * 180怎么會(huì)等于125.99999999998,坑也太多了吧!那時(shí)我猜測(cè)是二進(jìn)制表示數(shù)值時(shí)發(fā)生round-off error所導(dǎo)致,但并不...
摘要:上一篇學(xué)習(xí)下一代語(yǔ)法一,我們學(xué)習(xí)了關(guān)于塊作用域變量或常量聲明和語(yǔ)法新的字符串拼接語(yǔ)法模版字面量數(shù)組元素或?qū)ο笤氐慕鈽?gòu)賦值和對(duì)象字面量簡(jiǎn)寫(xiě)的相關(guān)知識(shí)。這便是擴(kuò)展運(yùn)算符的用途之一。 本文同步 帶你入門(mén) JavaScript ES6 (二),轉(zhuǎn)載請(qǐng)注明出處。 上一篇學(xué)習(xí)下一代 JavaScript 語(yǔ)法: ES6 (一),我們學(xué)習(xí)了關(guān)于塊作用域變量或常量聲明 let 和 const 語(yǔ)法、...
摘要:由于浮點(diǎn)數(shù)不是精確的值,所以涉及小數(shù)的比較和運(yùn)算要特別小心。根據(jù)標(biāo)準(zhǔn),位浮點(diǎn)數(shù)的指數(shù)部分的長(zhǎng)度是個(gè)二進(jìn)制位,意味著指數(shù)部分的最大值是的次方減。也就是說(shuō),位浮點(diǎn)數(shù)的指數(shù)部分的值最大為。 一 前言 這篇文章主要解決以下三個(gè)問(wèn)題: 問(wèn)題1:浮點(diǎn)數(shù)計(jì)算精確度的問(wèn)題 0.1 + 0.2; //0.30000000000000004 0.1 + 0.2 === 0.3; // ...
摘要:本文通過(guò)介紹的二進(jìn)制存儲(chǔ)標(biāo)準(zhǔn)來(lái)理解浮點(diǎn)數(shù)運(yùn)算精度問(wèn)題,和理解對(duì)象的等屬性值是如何取值的,最后介紹了一些常用的浮點(diǎn)數(shù)精度運(yùn)算解決方案。浮點(diǎn)數(shù)精度運(yùn)算解決方案關(guān)于浮點(diǎn)數(shù)運(yùn)算精度丟失的問(wèn)題,不同場(chǎng)景可以有不同的解決方案。 本文由云+社區(qū)發(fā)表 相信大家在平常的 JavaScript 開(kāi)發(fā)中,都有遇到過(guò)浮點(diǎn)數(shù)運(yùn)算精度誤差的問(wèn)題,比如 console.log(0.1+0.2===0.3)// fa...
閱讀 3698·2021-09-07 10:19
閱讀 3639·2021-09-03 10:42
閱讀 3592·2021-09-03 10:28
閱讀 2560·2019-08-29 14:11
閱讀 819·2019-08-29 13:54
閱讀 1605·2019-08-29 12:14
閱讀 426·2019-08-26 12:12
閱讀 3624·2019-08-26 10:45