Javascript中的函數(shù)與數(shù)值計(jì)算經(jīng)常被用到,其中小數(shù)相加也是一種非常普遍的需求。小數(shù)相加存在一個(gè)非常重要的問(wèn)題:精度。Javascript中的小數(shù)是通過(guò)IEEE754標(biāo)準(zhǔn)實(shí)現(xiàn)的,但是在進(jìn)行小數(shù)計(jì)算時(shí)由于精度問(wèn)題可能會(huì)導(dǎo)致結(jié)果出現(xiàn)奇怪的錯(cuò)誤。下面將會(huì)介紹幾種在Javascript中實(shí)現(xiàn)小數(shù)相加的方法。
我們先來(lái)看一個(gè)簡(jiǎn)單的例子,在Javascript中計(jì)算0.1+0.2時(shí)會(huì)得到什么結(jié)果:
console.log(0.1 + 0.2);
這樣的代碼輸出結(jié)果為0.30000000000000004。我們期望的結(jié)果應(yīng)該是0.3,但是計(jì)算結(jié)果卻出現(xiàn)了精度問(wèn)題。那么這個(gè)問(wèn)題該如何解決呢?
第一種方法是使用toFixed()轉(zhuǎn)化為字符串后再進(jìn)行小數(shù)計(jì)算。例如,如果我們要計(jì)算0.1+0.2并輸出結(jié)果:
let result = (0.1 + 0.2).toFixed(2); console.log(parseFloat(result));
這條代碼運(yùn)行輸出結(jié)果為0.30。toFixed()方法會(huì)將小數(shù)轉(zhuǎn)化為字符串并保留制定的小數(shù)位數(shù),在進(jìn)行parseFloat()解析為小數(shù)。但是這種方法存在一個(gè)缺陷,如果小數(shù)位數(shù)不同的話,可能會(huì)出現(xiàn)不正確的計(jì)算結(jié)果。
第二種方法是使用Math庫(kù)中的round方法。例如,如果我們要計(jì)算0.1+0.2并輸出結(jié)果:
let result = Math.round((0.1 + 0.2) * 100) / 100; console.log(result);
這條代碼運(yùn)行輸出結(jié)果為0.3。這種方法會(huì)將小數(shù)乘以一個(gè)倍數(shù)后進(jìn)行四舍五入,然后再除以倍數(shù)轉(zhuǎn)換為正確的小數(shù)。但是這種方法同樣存在一個(gè)缺陷,如果小數(shù)位數(shù)不同的話,也會(huì)出現(xiàn)不正確的計(jì)算結(jié)果。
第三種方法是使用第三方的Javascript庫(kù)decimal.js。decimal.js是一個(gè)能夠進(jìn)行高精度計(jì)算的庫(kù),在進(jìn)行小數(shù)計(jì)算時(shí)能夠保證精度不丟失。例如,如果我們要計(jì)算0.1+0.2并輸出結(jié)果:
let result = new Decimal(0.1).plus(0.2); console.log(result.toString());
這條代碼運(yùn)行輸出結(jié)果為0.3。decimal.js使用了BigInteger.js來(lái)實(shí)現(xiàn)高精度計(jì)算,能夠在進(jìn)行小數(shù)計(jì)算時(shí)保證精度。但是使用decimal.js的缺點(diǎn)是需要引入第三方庫(kù),而且執(zhí)行速度也會(huì)慢于原生Javascript的計(jì)算速度。
綜上所述,Javascript中實(shí)現(xiàn)小數(shù)相加存在著精度問(wèn)題。在進(jìn)行小數(shù)計(jì)算時(shí)需要注意精度,可以采用字符串轉(zhuǎn)化、Math庫(kù)中的方法或第三方庫(kù)來(lái)解決精度的問(wèn)題。