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

JS中toFixed()方法四舍五入的精度問題詳解

 更新時間:2021年10月12日 10:41:30   作者:橙某人  
最近在做項目的時候,遇到了有四舍五入保留兩位的需求,當時不假思索的直接使用了js原生的toFixed方法,結果出現(xiàn)了問題,這篇文章主要給大家介紹了關于JS中toFixed()方法四舍五入精度問題的相關資料,需要的朋友可以參考下

踩的坑

最近工作中,在計算一個商品的折扣價格,有時候總是出現(xiàn)價格會有一分錢的差異,涉及錢的問題都是比較敏感的,經過排查,最后發(fā)現(xiàn)竟然是 JS 原生的 toFixed 方法的問題。

好家伙,這都啥規(guī)律啊。。。(⊙o⊙)

填坑方法

先不著急去探究其中的問題,既然發(fā)現(xiàn)了問題,那就先把 Bug 修復了先,原生方法用不了,就自己寫一個唄,還不是分分鐘的事情,哈哈哈!

/**
 * 保留小數(shù)點幾位數(shù), 自動補零, 四舍五入
 * @param num: 數(shù)值
 * @param digit: 小數(shù)點后位數(shù)
 * @returns string
 */ 
function myFixed(num, digit) {
  if(Object.is(parseFloat(num), NaN)) {
    return console.log(`傳入的值:${num}不是一個數(shù)字`);
  }
  num = parseFloat(num);
  return (Math.round((num + Number.EPSILON) * Math.pow(10, digit)) / Math.pow(10, digit)).toFixed(digit);
}

什么樣的坑?

好了,既然 Bug 解決完了,下面我們就來探索一下 toFixed 其中的奧秘。

呃...首先,Em...百度一下吧,面向百度編程工程師,果然一查大把結果,看來是個經典問題了。

經過一番了解得知,原來是 toFixed 方法采用的四舍五入,并不是我們理解的字面上的四舍五入。而 toFixed 方法它是采用一種詭異的方法 "四舍六入五取偶" ,也叫銀行家算法,這是什么個意思呢?

完整說法:"四舍六入五考慮,五后非零就進一,五后為零看奇偶,五前為偶應舍去,五前為奇要進一"。

大概意思是:當舍去位的數(shù)值 ≤4 時舍去,當它 ≥6 時加上,可當它 =5 時,則根據(jù) 5 后面的數(shù)字來定;當 5 后有非零數(shù)字時,舍 5 入 1;當 5 后無有效數(shù)字時,需要再分兩種情況:5 前為偶數(shù),舍 5 不進;5 前為奇數(shù),舍 5 入 1 。

根據(jù)這個規(guī)則,我在瀏覽器上又跑了一些測試,但卻還是感覺不對。

// 五前是偶數(shù),沒有舍去?
console.log(1.00000065.toFixed(7)); // 1.0000007 錯誤
console.log(1.000000065.toFixed(8)); // 1.00000007 錯誤
// 五前是奇數(shù),沒有進一?
console.log(1.00000015.toFixed(7)); // 1.0000001 錯誤
console.log(1.000000015.toFixed(8)); // 1.00000001 錯誤

這到底為啥?真是讓人摸不著頭腦。。。(︶︿︶)

再經過一番探索,總算是有點收獲了,下面就得來看看 ECMAScript 規(guī)范對該方法的定義了,有時候回歸規(guī)范才是最靠譜的方式。

上圖是關于整個 toFixed 方法的定義,不過是翻譯后的版本,會有出入但差別不大,也可以點擊上面的鏈接查看原文,我們主要關注圖中紅框部分,通過公式來計算舍去位數(shù)值。

我們下面兩個來舉個栗子,測試一下。

console.log(1.0000005.toFixed(6)); // 1.000001 正確
console.log(1.00000005.toFixed(7)); // 1.0000000 錯誤  

首先,根據(jù)紅框的條件,x<10^21,1.0000005 與 1.00000005 都是小于 10^21 的,所以我們直接可以使用公式 n / 10^ - x 來玩耍。

我們先用 x=1.0000005 代入公式來看看情況:

// 假設n1
var n1 = 1000000;
var x = 1.0000005;
var f = 6;
console.log((n1 / Math.pow(10, f) - x)); // -5.00000000069889e-7

// 假設n2
var n2 = 1000001;
var x = 1.0000005;
var f = 6;
console.log((n2 / Math.pow(10, f) - x)); // 4.999999998478444e-7

由結果可知,當 n1=1000001 時,得到的結果取最接近 0 的值,故:

console.log(1.0000005.toFixed(6)); // 1.000001 正確

再來試試當 x=1.00000005 代入公式:

// 假設n1
var n1 = 10000000;
var x = 1.00000005;
var f = 7;
console.log((n1 / Math.pow(10,f) - x)); // -4.9999999918171056e-8

// 假設n2
var n2 = 10000001;
var x = 1.00000005;
var f = 7;
console.log((n2 / Math.pow(10,f) - x)); // 5.000000014021566e-8

由結果可知,當 n2=10000001 時,得到的結果取最接近 0 的值,故:

console.log(1.00000005.toFixed(7)); // 1.0000000 錯誤

哎...寫到這里才發(fā)現(xiàn)給自己挖了一個大坑,干嘛要搞那么多零,自己都數(shù)暈圈了。。。

總的來說,上面例子就是教你如何通過規(guī)范定義的公式計算出結果而已,如果你看得懂規(guī)范,那么直接去代入也是沒有問題的。

總結

到此這篇關于JS中toFixed()方法四舍五入精度問題的文章就介紹到這了,更多相關JS toFixed()四舍五入精度問題內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

三门县| 卢湾区| 华宁县| 临泉县| 乌兰县| 文安县| 华安县| 措勤县| 石楼县| 秦皇岛市| 弥渡县| 建昌县| 丰台区| 紫云| 甘孜| 革吉县| 金昌市| 崇左市| 武穴市| 富锦市| 囊谦县| 新田县| 尚义县| 凤冈县| 金坛市| 泸水县| 清丰县| 灵寿县| 五指山市| 台州市| 新平| 呈贡县| 龙游县| 堆龙德庆县| 翁源县| 天镇县| 许昌县| 三江| 建湖县| 林州市| 峨眉山市|