이 글은 주로 Javascript의 toFixed 계산 오류(뱅커의 반올림 방식에 의존하는 결함)에 대한 해결책을 소개합니다. 도움이 필요한 친구들이 참고할 수 있습니다.
서문
회사 프로젝트에는 부동 소수점 가격 계산 모듈이 많이 있어서 다음과 같은 생각이 들었습니다.
컴퓨터 바이너리 환경에서 부동 소수점 숫자의 계산 정밀도가 부족한 문제
console.log(.1+.2); 0.30000000000000004
위의 문제를 해결하기 위해 toFixed 메소드를 사용했지만 오류가 발생했습니다. 소수점 이하 자릿수가 5로 끝나는 반올림 오류 문제
var num = 0.045; console.log(num.toFixed(2)); 0.04
이것을 출발점으로 삼아 일련의 탐구가 시작되었습니다. toFixed, 그리고 마침내 몇 가지 유용한 정보를 찾았습니다. toFixed에서 사용하는 계산 규칙은 다음과 같습니다.
뱅커 반올림: 소위 뱅커 반올림 방법은 본질적으로 반올림 짝수(5반올림이라고도 함)입니다. 짝수) 방식.
간단히 말하면: 5로 반올림하는 것을 고려하세요. 5 이후의 숫자가 0이 아니면 1을 더하고, 5 이후의 숫자가 0이면 홀수 또는 짝수로 보고, 5 이전의 숫자가 짝수이면 5 이전의 숫자가 홀수이면 1로 반올림합니다.
Text
이제 우리는 소위 은행가의 반올림 방법을 검증할 것입니다. 검증은 4, 5, 6을 반올림 비트로 사용하여 고정되었습니다(예: Chrome 사용).
4를 반올림 숫자로 사용:
var num = 0.004; console.log(num.toFixed(2)); 0.00 var num = 0.014; console.log(num.toFixed(2)); 0.01 var num = 0.094; console.log(num.toFixed(2)); 0.094의 끝 부분에 있는 이 상황에서 toFixed는 꽤 잘 수행되며 오류 문제도 없습니다.
6을 반올림 숫자로 사용하세요.
var num = 0.006; console.log(num.toFixed(2)); 0.01 var num = 0.016; console.log(num.toFixed(2)); 0.02 var num = 0.096; console.log(num.toFixed(2)); 0.10은 6으로 끝납니다. 이 경우 toFixed도 잘 수행되며 오류 문제가 없습니다.
반올림 숫자로 5 사용:
var num = 0.0051; console.log(num.toFixed(2)); 0.01 var num = 0.0052; console.log(num.toFixed(2)); 0.01 var num = 0.0059; console.log(num.toFixed(2)); 0.01규칙에 따르면 5 이후 0이 아닌 경우 1이 고급이 아닌 것으로 확인되었습니다. 문제.
5를 반올림 숫자로 사용:
var num = 0.005; console.log(num.toFixed(2)); var num = 0.015; console.log(num.toFixed(2)); var num = 0.025; console.log(num.toFixed(2)); var num = 0.035; console.log(num.toFixed(2)); var num = 0.045; console.log(num.toFixed(2)); var num = 0.055; console.log(num.toFixed(2)); var num = 0.065; console.log(num.toFixed(2)); var num = 0.075; console.log(num.toFixed(2)); var num = 0.085; console.log(num.toFixed(2)); var num = 0.095; console.log(num.toFixed(2));Chrome, Firefox, Safari, Opera의 결과는 다음과 같습니다. 0.01
0.01
0.03
0.04
0.04
0.06
0.07
0.07
0.09
0.10
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.10
Solution
아래에서는 Fixed를 다시 작성하여 메서드를 제공합니다.Number.prototype.toFixed = function(length) { var carry = 0; //存放进位标志 var num,multiple; //num为原浮点数放大multiple倍后的数,multiple为10的length次方 var str = this + ''; //将调用该方法的数字转为字符串 var dot = str.indexOf("."); //找到小数点的位置 if(str.substr(dot+length+1,1)>=5) carry=1; //找到要进行舍入的数的位置,手动判断是否大于等于5,满足条件进位标志置为1 multiple = Math.pow(10,length); //设置浮点数要扩大的倍数 num = Math.floor(this * multiple) + carry; //去掉舍入位后的所有数,然后加上我们的手动进位数 var result = num/multiple + ''; //将进位后的整数再缩小为原浮点数 /* * 处理进位后无小数 */ dot = result.indexOf("."); if(dot < 0){ result += '.'; dot = result.indexOf("."); } /* * 处理多次进位 */ var len = result.length - (dot+1); if(len < length){ for(var i = 0; i < length - len; i++){ result += 0; } } return result; }이 메서드의 일반적인 아이디어는 먼저 반올림 비트를 찾아 위치가 다음보다 큰지 확인하는 것입니다. 5와 같거나 5인 조건 수동 캐리를 1비트로 설정한 다음 매개변수 크기를 사용하여 원래 부동 소수점 수를 매개변수 지수배 10배로 증폭한 다음 플로어를 사용하여 반올림 비트를 포함한 모든 숫자를 제거하고 결정합니다. 이전 수동 캐리를 기준으로 캐리 여부를 결정합니다.
위 내용은 Javascript의 계산 오류 수정에 대한 해결 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!