js 에서 toFixed 정밀도 문제 해결 방법

3520 단어
최근 프로젝트 를 할 때 반올림 으로 두 분 을 유지 하 는 수 요 를 만 났 습 니 다. 그 당시 에는 생각 하지 않 고 js 원생 의 toFixed 방법 을 직접 사용 하여 문제 가 많 았 습 니 다.주로 다음 과 같은 몇 가지 문제 가 있다.
반올림 은 진정한 반올림 이 아니다.
이 문 제 는 테스트 단계 에서 우리 의 테스트 인원 이 제기 한 것 이다.처음에 저도 놀 랐 습 니 다. 결국 콘 솔 에서 데 이 터 를 테스트 한 후에 저 는 멍 해 졌 습 니 다. 제 가 계속 사용 하 던 toFixed 방법 에 문제 가 생 겼 습 니 다. 제 가 어리석게 그것 으로 많은 일 을 했 습 니 다!다음은 내 가 chrome 에서 의 결과 이다.
1.35.toFixed(1) // 1.4   
1.335.toFixed(2) // 1.33    
1.3335.toFixed(3) // 1.333   
1.33335.toFixed(4) // 1.3334   
1.333335.toFixed(5)  // 1.33333   
1.3333335.toFixed(6) // 1.333333   

역시 문제 가 있어 서 인터넷 에서 자 료 를 찾 을 수 밖 에 없 었 습 니 다. 그 결과 똑 같은 위의 코드 인 것 을 발 견 했 습 니 다. IE 에서 작은 차이 점 이 있 습 니 다. 다음은 IE 의 결과 입 니 다.
1.35.toFixed(1) // 1.4   
1.335.toFixed(2) // 1.34    
1.3335.toFixed(3) // 1.334   
1.33335.toFixed(4) // 1.3334   
1.333335.toFixed(5)  // 1.33334   
1.3333335.toFixed(6) // 1.333334   

역시 IE 가 아빠 야.혹시 브 라 우 저 호환성 문제 인가요?호환성 문 제 는 IE 에서 나 와 야 하지 않 겠 습 니까?문제 의 소 재 를 찾 은 이상 착수 하기 쉽다.내 방법 은 반올림 할 사람 을 따로 들 고 판단 하 는 거 야.
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);

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

return result;

자기가 몇 번 재 봤 는데 괜 찮 을 것 같 아 요. OK ~
2. 컴퓨터 바 이 너 리 인 코딩 으로 인 한 정밀도 문제
얼마 지나 지 않 아 테스트 에서 페이지 가 잘못 되 었 습 니 다 ~ 마음 이 답답 합 니 다. 어떻게 잘못 되 었 을 수 있 습 니까?자신의 debugger 는 페이지 의 js 가 순환 에 들 어간 것 을 발견 했다.분명 한 문 제 는 toFixed 에서 toFixed 를 되 돌 렸 는데 결과 가 나 오지 않 고 debugger 를 계속 하 다가 또 사람 이 들 어 온 것 을 발견 했다.다음은 콘 솔 테스트:
console.log(2.115 * 100) // 211.50000000000003
console.log(2.0115 * 1000) // 2011.4999999999998

무슨 짓 을 하 는 지 알려 주 시 겠 어 요?좋아, 내 가 알 아 맞 혔 어. 틀림없이 컴퓨터 의 진도 문제 일 거 야.네가 계속 순환 에 들 어간 이상 나 는 수 동 으로 너 를 끌 어 낼 것 이다.
result = (Math.round((parseFloat(result)) * x) + 1) / x;

사사오입 을 강제 하여 정돈 하면 사순환 에 들 어가 지 않 을 것 이다!
다음은 모든 코드 입 니 다.
// 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('.');

    //      
    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);

    //     ,        ,          
    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;
};

좋은 웹페이지 즐겨찾기