toFixed方法的bug之解决方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了toFixed方法的bug之解决方法相关的知识,希望对你有一定的参考价值。

最近在工作过程中碰到一个隐藏的bug,经调试发现竟然是toFixed函数不可靠的结果引起的。后端同学在处理价格比较的时候,用foFixed进行价格的四舍五入之后,竟然发现比较的结果有问题;

大家都知道,Number类型的变量有个toFixed方法,该方法将Number四舍五入为指定小数位数的数字,以字符串返回。

IE:

0.6 .toFixed(0); // 0
1.6 .toFixed(0); // 2

Chrome:

0.6 .toFixed(0); // 1
1.6 .toFixed(0); // 2

另外还发现,就算是同在Chrome里,四舍五入也不靠谱:

( 0.035 ).toFixed( 2 ); // 0.04
( 0.045 ).toFixed( 2 ); // 0.04

这次IE倒是靠谱了:

( 0.035 ).toFixed( 2 ); // 0.04
( 0.045 ).toFixed( 2 ); // 0.05

结论 :toFixed()函数靠不住,如果有需要精确控制的情况,还是自己写个方法比较好。比如:

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(‘‘);
}
var a = 19.02
var b = 209.01
// 结果
console.log(toFixed(a, 2)); //==> 19.02
console.log(toFixed(b, 2)); //==> 209.01
console.log(Number(toFixed(a, 2)) < Number(toFixed(b, 2))); //==> true

以上是关于toFixed方法的bug之解决方法的主要内容,如果未能解决你的问题,请参考以下文章

ToFixed()用于四舍五入的问题及解决方法

js中Number.toFixed()方法的理解

控制小数位数

React16.7 hooks之setTimeout引发的bug小记

React—Native开发之 Could not connect to development server(Android)解决方法

toFixed()方法