Improvement of JavaScript rounding

Preface

In recent two projects, there are parts related to data statistics. Generally speaking, the amount data is to save 2 decimal places. Previously, the toFixed method using JavaScript native object Number was used. However, the problem of 3.235.toFixed(2) = 3.23 appeared in the test. After checking the following data, it is found that the problem is caused by the storage of floating-point numbers. Finally, I encapsulated a function to solve this problem.

1. Reasons for the loss of accuracy of ToFixed

I don't know much about floating-point storage. I recommend this article to the students who need it JavaScript floating point trap and its solution.

2. Package toFixed

2-1 implementation ideas

  • The general idea is divided into two parts, one is the integer part. The integer part does not need to be modified. In order to keep consistent with Number.toFixed, the corresponding 0 (8. ToFixed (2) = > 8.00) needs to be added;
  • There are three judgments to be made for the decimal part. The current number of decimal places is compared with the number of decimal places to be saved. If the number of decimal places is less than the number of decimal places to be saved, the redundant part will be discarded. In the last case, different processing should be carried out for positive and negative numbers. See the code below for details.
  • Note: the returned results are all strings.

2-2 code

let tofixed = (value, holdLen) => {
    value = value.toString();
    let dotIndex = value.indexOf(".");
    //Judge whether it is an integer
    if (dotIndex === -1) {
        //Fill in a few zeros if there are few
        let integerStr = ".";
        for (let i = 0; i < holdLen; i++) {
            integerStr = integerStr + '0';
        }
        return value + integerStr;
    }
    //Get the string before and after the decimal point
    let dotBefore = value.split(".")[0];
    let dotAfter = value.split(".")[1];
    //After the decimal point, judge the number of digits to be reserved
    let result = "";
    if (dotAfter.length === holdLen) {
        result = value;
    } else if (dotAfter.length < holdLen) {
        let forlength = holdLen - dotAfter.length
        //Fill in a few zeros if there are few
        for (let i = 0; i < forlength; i++) {
            dotAfter = dotAfter + '0';
        }
        result = dotBefore + "." + dotAfter;
    } else {
        //Gets the value of the number after the position to be rounded
        let digit = value.substr(dotIndex + holdLen + 1, 1);
        if (digit >= 5) {
            let temp = Math.pow(10, 0 - holdLen);
            //Rounding judgment of negative and positive numbers
            parseFloat(value) > 0 ? value = parseFloat(value) + temp : value = parseFloat(value) - temp;
            value = value.toString();
        }
        result = value.substr(0, dotIndex + holdLen + 1);
    }
    return result;
}
console.log(tofixed(1.335, 2));
console.log(tofixed(2.1, 3));
console.log(tofixed(-8.546, 2));
console.log(tofixed(-9, 3));

//Print results
"1.34"
"2.100"
"-8.55"
"-9.000"

My approach is very rough. I hope you will give me more comments.

Tags: Javascript less

Posted on Sun, 01 Dec 2019 16:07:27 -0800 by Shuriken1