美文网首页
JS toFixed()填坑

JS toFixed()填坑

作者: 涅槃快乐是金 | 来源:发表于2022-12-08 22:17 被阅读0次

    问题

    1、在JS中四舍五入的函数 toFixed(n) , n为要保留的小数位数。 n为0~20,当n超过20的时候,JS会出错。

    2、当截取小数点前一位是0时,输出结果可能会有所不同。

    var a = 0.145;
    
    a.toFixed(2);
    
    //结果为0.14;
    

    靠谱分析

    学会查标准
    摘自ECMA-262 5.1 Edition

    15.7.4.5 Number.prototype.toFixed (fractionDigits)
    
    Return a String containing this Number value represented in decimal fixed-point notation with fractionDigits 
    digits after the decimal point. If fractionDigits is undefined, 0 is assumed. Specifically, perform the following 
    steps: 
    1. Let f be ToInteger(fractionDigits). (If fractionDigits is undefined, this step produces the value 0). 
    2. If f < 0 or f > 20, throw a RangeError exception. 
    3. Let x be this Number value. 
    4. If x is NaN, return the String "NaN". 
    5. Let s be the empty String. 
    6. If x < 0, then 
    a. Let s be "-". 
    b. Let x = –x. 
    7. If x >= 10^21, then 
    a. Let m = ToString(x). 
    8. Else, x < 10^21
    a. Let n be an integer for which the exact mathematical value of n / 10^f – x is as close to zero as possible. If there are two such n, pick the larger n. 
    b. If n = 0, let m be the String "0". Otherwise, let m be the String consisting of the digits of the decimal representation of n (in order, with no leading zeroes). 
    c. If f != 0, then 
    i. Let k be the number of characters in m. 
    ii. If k ≤ f, then 
    1. Let z be the String consisting of f+1–k occurrences of the character '0'. 
    2. Let m be the concatenation of Strings z and m. 
    3. Let k = f + 1. 
    iii. Let a be the first k–f characters of m, and let b be the remaining f characters of m. 
    iv. Let m be the concatenation of the three Strings a, ".", and b. 
    9. Return the concatenation of the Strings s and m. 
    

    根据上述步骤

    9.955.toFixed(2)的过程为

    1. f = 2
    3. x = 9.955
    5. s = ''
    8.
    
    a. n = 996
    原因
    当 n = 995 时 n / 10^f – x = -0.005000000000000782
    当 n = 996 时 n / 10^f – x = 0.005000000000000782
    同样靠近0, 选择大的那个
    b. m = '996'
    c.
    i. k = 3
    iii. a = '9', b = '96'
    iv. m = a + '.' + b = '9.96'
    9. Return s + m = '9.96'
    

    9.655.toFixed(2)的过程为

    1. f = 2
    3. x = 9.655
    5. s = ''
    8.
    
    a. n = 965
    原因
    当 n = 965 时 n / 10^f – x = -0.004999999999999005
    当 n = 966 时 n / 10^f – x = 0.005000000000000782
    965更靠近0
    b. m = '965'
    c.
    i. k = 3
    iii. a = '9', b = '65'
    iv. m = a + '.' + b = '9.65'
    9. Return s + m = '9.65'
    

    简而言之其实还是浮点误差的锅

    修复

    function toFixed(number, decimal) {
        decimal = decimal || 0;
        var s = String(number);
        var decimalIndex = s.indexOf('.');
        if (decimalIndex < 0) {
            var fraction = '';
            for (var i = 0; i < decimal; i++) {
                fraction += '0';
            }
            return s + '.' + fraction;
        }
        var numDigits = s.length - 1 - decimalIndex;
        if (numDigits <= decimal) {
            var fraction = '';
            for (var i = 0; i < decimal - numDigits; i++) {
                fraction += '0';
            }
            return s + fraction;
        }
        var digits = s.split('');
        var pos = decimalIndex + decimal;
        var roundDigit = digits[pos + 1];
        if (roundDigit > 4) {
            //跳过小数点
            if (pos == decimalIndex) {
                --pos;
            }
            digits[pos] = Number(digits[pos] || 0) + 1;
            //循环进位
            while (digits[pos] == 10) {
                digits[pos] = 0;
                --pos;
                if (pos == decimalIndex) {
                    --pos;
                }
                digits[pos] = Number(digits[pos] || 0) + 1;
            }
        }
        //避免包含末尾的.符号
        if (decimal == 0) {
            decimal--;
        }
        return digits.slice(0, decimalIndex + decimal + 1).join('');
    }
    

    实验:

    toFixed(0.0056,2)
    //'0.01'
    toFixed(298561.7249999999999999,2)
    //'298561.73'
    toFixed(298561.7249999999999999,3)
    //'298561.725'
    

    相关文章

      网友评论

          本文标题:JS toFixed()填坑

          本文链接:https://www.haomeiwen.com/subject/ienafdtx.html