日期:2014-05-16  浏览次数:20395 次

JS精度问题

在JS处理算法时,有时会存在精度问题。

?

如694.84+(-300)有精度问题,但694.64+(-300)没有精度问题。




如0.263*256.3有精度问题,但0.263*256.5没有精度问题。



?

?

但在实际应用中,是绝对不能出现此类问题的。如下提供了一种解决此类精度问题的方法,供参考。

?

<html>
<head></head>
<script>
/**
 *
 * 浮点数乘法运算
 *
 * @param {number} arg1 乘数
 * @param {number} arg2 被乘数
 *
 * @example
 * Math.floatMul(11.1, 77.7)
 * 其形式等同于 (11.1 * 77.7) 但不存在 JS 丢失精度的问题
 * 如3.69 * 258.258
 */
Math.floatMul = function(arg1, arg2) {
	var m=0, s1=arg1.toString(), s2=arg2.toString();    
	try{ m += s1.split(".")[1].length; } catch(e){}
	try{ m += s2.split(".")[1].length; } catch(e){}
	//alert(s1 + '|||' + s2);
	return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
};
/**
 * 浮点数加法运算   
 *
 * @param {number} arg1 加数
 * @param {number} arg2 被加数
 *
 * @example
 * Math.floatAdd(11.1, 77.7)
 * 其形式等同于 (11.1 + 77.7) 但不存在 JS 丢失精度的问题
 * 如694.84 + (-300)
 */
Math.floatAdd = function(arg1, arg2) {   
	var r1, r2, m;   
	try{ r1 = arg1.toString().split(".")[1].length; } catch(e) { r1 = 0; }
	try{ r2 = arg2.toString().split(".")[1].length; } catch(e) { r2 = 0; }
	m = Math.pow(10, Math.max(r1, r2));
	return ((arg1 * m) + (arg2 * m)) / m;
};

/**
 * 直接乘
 */
function directMul(){
	var v1 = document.getElementById('txt1').value;
	var v2 = document.getElementById('txt2').value;
	var v = parseFloat(v1) * parseFloat(v2);
	alert(v1 + ' * ' + v2 + ' = ' + v);
}

/**
 * 帮助方法乘
 */
function helpMul(){
	var v1 = document.getElementById('txt1').value;
	var v2 = document.getElementById('txt2').value;
	var v = Math.floatMul(parseFloat(v1), parseFloat(v2));
	alert(v1 + ' * ' + v2 + ' = ' + v);
}

/**
 * 直接加
 */
function directAdd(){
	var v1 = document.getElementById('txt1').value;
	var v2 = document.getElementById('txt2').value;
	var v3 = parseFloat(v1) + parseFloat(v2);
	alert(v1 + ' + ' + v2 + ' = ' + v3);
}

/**
 * 帮助方法加
 */
function helpAdd(){
	var v1 = document.getElementById('txt1').value;
	var v2 = document.getElementById('txt2').value;
	v = Math.floatAdd(parseFloat(v1), parseFloat(v2));
	alert(v1 + ' + ' + v2 + ' = ' + v);
}

/**
 * 条件修改
 */
function conditionModify(){
	var v1 = document.getElementById('txt1').value;
	var v2 = document.getElementById('txt2').value;
	var b = compareModifyValIsIncluded({
	                             normVal   : v1
	                           , modifyVal : v2
	                           , minScale  : -0.4
	                           , maxScale  : 0.3
	});
	//alert(b);
	if(b) {
		document.getElementById('txt1').value = v2;
	}
}

/**
 * 判断原值是否在修改的范围内,如在范围内,返回true;如不在范围内,返回false
 */
var compareModifyValIsIncluded = function (includeParamObj){
	if(theParamsIsNaN(includeParamObj.normVal, includeParamObj.modifyVal)) {
		return false;
	}
	if(theParamsIsNaN(includeParamObj.minScale, includeParamObj.maxScale)) {
		return false;
	}
	// 原值
	var normVal = parseFloat(includeParamObj.normVal);
	// 预修改后的值
	var modifyVal = parseFloat(includeParamObj.modifyVal);
	// 修改上限
	var maxScale = parseFloat(includeParamObj.maxScale);
	// 修改下限
	var minScale = parseFloat(includeParamObj.minScale);
	var maxVal = Math.floatMul(normVal, 1 + maxScale);
	var mixVal = Math.floatMul(normVal, 1 + minScale);
	//alert('maxScale:' + maxScale + ' || minScale:' + minScale);
	//alert(normVal + 'maxVal:' + maxVal + '||mixVal' + mixVal);
	if(modifyVal < mixVal || modifyVal > maxVal) {
		return true;
	}
	return false;
}

var theParamsIsNaN = function (){
	for(var i = 0 ; i < arguments.length ; i++){
		if(isNaN(arguments[i])) {
	  	return true;
	  }
	}
	return false;
}
</script>

<body>
	<input id="txt1" /><br/>
	<input id="txt2" /><br/>
	<input type="button" value="直接乘" onclick="directMul()" />