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

JS中toFixed(2)精度問(wèn)題的原因以及解決辦法

 更新時(shí)間:2024年04月29日 11:51:54   作者:喝一杯維C  
最近發(fā)現(xiàn)JS當(dāng)中toFixed()方法存在一些問(wèn)題,所以這里給大家總結(jié)下,這篇文章主要給大家介紹了關(guān)于JS中toFixed(2)精度問(wèn)題的原因以及解決辦法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

toFixed() 方法可把 Number 四舍五入為指定小數(shù)位數(shù)的數(shù)字。例如將數(shù)據(jù)Num保留2位小數(shù),則表示為:toFixed(Num);但是其四舍五入的規(guī)則與數(shù)學(xué)中的規(guī)則不同,使用的是銀行家舍入規(guī)則,銀行家舍入:所謂銀行家舍入法,其實(shí)質(zhì)是一種四舍六入五取偶(又稱四舍六入五留雙)法。具體規(guī)則如下:簡(jiǎn)單來(lái)說(shuō)就是:四舍六入五考慮,五后非零就進(jìn)一,五后為零看奇偶,五前為偶應(yīng)舍去,五前為奇要進(jìn)一。

經(jīng)測(cè)試發(fā)現(xiàn),在chorme下面,并沒(méi)有完全遵守這個(gè)規(guī)則,尤其是5的后面沒(méi)有數(shù)字的時(shí)候,不是這么判斷的,如下:

var b = 1.335

b.toFixed(2)

"1.33"

var b = 1.345

b.toFixed(2)

"1.34"

var b = 1.355

b.toFixed(2)

"1.35"

var b = 1.365

b.toFixed(2)

"1.36"

var b = 1.375

b.toFixed(2)

"1.38"

var b = 1.385

b.toFixed(2)

"1.39"

可以發(fā)現(xiàn)在chorme下沒(méi)有完全去遵循這個(gè)規(guī)律,或許它有自己的算法,但是畢竟它沒(méi)有遵循通用的銀行家算法,所以tofixed這個(gè)方法在涉及到金錢(qián)計(jì)算的業(yè)務(wù)中還是少用.

總而言之:不論引入toFixed解決浮點(diǎn)數(shù)計(jì)算精度缺失的問(wèn)題也好,它有沒(méi)有使用銀行家舍入法也罷,都是為了解決精度的問(wèn)題,但是又離不開(kāi)二進(jìn)制浮點(diǎn)數(shù)的環(huán)境,但至少他幫助我們找到了問(wèn)題所在,從而讓我們有解決方法。

一開(kāi)始的辦法是把要四舍五入的后一位單獨(dú)拎出來(lái)單獨(dú)判斷。

解決方法:

通過(guò)重寫(xiě)toFixed方法:

Number.prototype.toFixed = function (n) {
let result = number.toString();
const arr = result.split('.');
const integer = arr[0];
const decimal = arr[1];
result = integer + '.' + decimal.substr(0, n);
const last = decimal.substr(n, 1);

// 四舍五入,轉(zhuǎn)換為整數(shù)再處理,避免浮點(diǎn)數(shù)精度的損失

if (parseInt(last, 10) >= 5) {
const x = Math.pow(10, n);
result = ((parseFloat(result) * x) + 1) / x;
result = result.toFixed(n);
}
return result;
}

然后又發(fā)現(xiàn)計(jì)算機(jī)二進(jìn)制編碼導(dǎo)致的精度問(wèn)題,詳見(jiàn)上一篇博客。

自己debugger,發(fā)現(xiàn)頁(yè)面中的js進(jìn)了死循環(huán)。很明顯問(wèn)題出在toFixed中回調(diào)了toFixed,結(jié)果沒(méi)有走出來(lái),繼續(xù)debugger,又有了驚人的發(fā)現(xiàn)。以下是控制臺(tái)測(cè)試:

console.log(2.115 * 100) // 211.50000000000003
console.log(2.0115 * 1000) // 2011.4999999999998

既然你一直進(jìn)入循環(huán),我就手動(dòng)把你拉出來(lái)。

result = (Math.round((parseFloat(result)) * x) + 1) / x;

最終完整的重寫(xiě)toFixed的方法

// toFixed兼容方法
Number.prototype.toFixed = function (n) {
    if (n > 20 || n < 0) {
        throw new RangeError('toFixed() digits argument must be between 0 and 20');
    }
    const number = this;
    if (isNaN(number) || number >= Math.pow(10, 21)) {
        return number.toString();
    }
    if (typeof (n) == 'undefined' || n == 0) {
        return (Math.round(number)).toString();
    }
    let result = number.toString();
    const arr = result.split('.');
    // 整數(shù)的情況
    if (arr.length < 2) {
        result += '.';
        for (let i = 0; i < n; i += 1) {
            result += '0';
        }
        return result;
    }
    const integer = arr[0];
    const decimal = arr[1];
    if (decimal.length == n) {
        return result;
    }
    if (decimal.length < n) {
        for (let i = 0; i < n - decimal.length; i += 1) {
            result += '0';
        }
        return result;
    }
    result = integer + '.' + decimal.substr(0, n);
    const last = decimal.substr(n, 1);
    // 四舍五入,轉(zhuǎn)換為整數(shù)再處理,避免浮點(diǎn)數(shù)精度的損失
    if (parseInt(last, 10) >= 5) {
        const x = Math.pow(10, n);
        result = (Math.round((parseFloat(result) * x)) + 1) / x;
        result = result.toFixed(n);
    }
    return result;
}

總結(jié) 

到此這篇關(guān)于JS中toFixed(2)精度問(wèn)題的原因以及解決辦法的文章就介紹到這了,更多相關(guān)js toFixed(2)精度問(wèn)題解決內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

巢湖市| 湘潭县| 射阳县| 姜堰市| 辽宁省| 丽江市| 尖扎县| 岑溪市| 邳州市| 黄平县| 双城市| 柘城县| 平安县| 清流县| 璧山县| 松桃| 德化县| 乐山市| 商都县| 济南市| 沙河市| 汪清县| 绩溪县| 康乐县| 皮山县| 同江市| 肇源县| 石狮市| 东海县| 绍兴县| 渑池县| 临清市| 宜州市| 新乡县| 竹溪县| 怀远县| 康平县| 五峰| 万山特区| 吉林省| 喀喇|