`

Javascript 浮点数精确计算

阅读更多
浮点数计算精度问题是javascript自身存在的问题。

比较经典的例子为2.0-1.1, 计算的结果为0.8999999999999999。

精确计算的基本思路是将其全部转换为整数后计算,整数计算不存在误差,然后再除以之前乘的数。

如下代码1为测试html,引用的js见代码2。也可以下载附件,附件中已经都包含。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>浮点数精确计算测试</title>
		<script type="text/javascript" src="js/FloatCumulateV1.js"></script>
		<script type="text/javascript">
		    window.onload = function(){
		    	document.getElementById("1").innerHTML = (0.01/0.1) ;
		    	document.getElementById("2").innerHTML = (Number(0.01).div(Number(0.1))) ;
		    	
		    	document.getElementById("3").innerHTML = (1.5*0.1) ;
		    	document.getElementById("4").innerHTML = (Number(1.5).mul(Number(0.1))) ;
		    	
		    	document.getElementById("5").innerHTML = (0.09999999+0.00000001) ;
		    	document.getElementById("6").innerHTML = (Number(0.09999999).add(Number(0.00000001))) ;
		    	
		    	document.getElementById("7").innerHTML = (2.0-1.1) ;
		    	document.getElementById("8").innerHTML = (Number(2.0).sub(Number(1.1))) ;
		    	
		    	document.getElementById("9").innerHTML = (Number(10).div(Number(0.1))) ;
		    	document.getElementById("10").innerHTML = (Number(10).mul(Number(0.1))) ;
		    	document.getElementById("11").innerHTML = (Number(10).add(Number(0.2))) ;
		    	document.getElementById("12").innerHTML = (Number(10).sub(Number(1.1))) ;
		    	
		    }
			
		</script>
	</head>
	<body>
		<h1>浮点数精确计算测试</h1>
		<p>普通js除法计算: 0.01/0.1 = <label id="1"> </label></p>
		<p>当前js除法计算: 0.01/0.1 = <label id="2"> </label></p>
		
		<p>普通js乘法计算: 1.5*0.1 = <label id="3"> </label></p>
		<p>当前js乘法计算: 1.5*0.1 = <label id="4"> </label></p>
		
		<p>普通js加法计算: 0.09999999+0.00000001 = <label id="5"> </label></p>
		<p>当前js加法计算: 0.09999999+0.00000001 = <label id="6"> </label></p>
		
		<p>普通js减法计算: 2.0-1.1 = <label id="7"> </label></p>
		<p>当前js减法计算: 2.0-1.1 = <label id="8"> </label></p>
		

		<p>当前js除法计算(不带小数,测试Exception的分支): 10/0.1 = <label id="9"> </label></p>		
		<p>当前js乘法计算(不带小数,测试Exception的分支): 10*0.1 = <label id="10"> </label></p>	
		<p>当前js加法计算(不带小数,测试Exception的分支): 10+0.2 = <label id="11"> </label></p>		
		<p>当前js减法计算(不带小数,测试Exception的分支): 10-1.1= <label id="12"> </label></p>
	</body>
</html>


此html运行结果:
浮点数精确计算测试

普通js除法计算: 0.01/0.1 = 0.09999999999999999

当前js除法计算: 0.01/0.1 = 0.1

普通js乘法计算: 1.5*0.1 = 0.15000000000000002

当前js乘法计算: 1.5*0.1 = 0.15

普通js加法计算: 0.09999999+0.00000001 = 0.09999999999999999

当前js加法计算: 0.09999999+0.00000001 = 0.1

普通js减法计算: 2.0-1.1 = 0.8999999999999999

当前js减法计算: 2.0-1.1 = 0.9

当前js除法计算(不带小数,测试Exception的分支): 10/0.1 = 100

当前js乘法计算(不带小数,测试Exception的分支): 10*0.1 = 1

当前js加法计算(不带小数,测试Exception的分支): 10+0.2 = 10.2

当前js减法计算(不带小数,测试Exception的分支): 10-1.1= 8.9

计算的JS
function accDiv(arg1, arg2)
{
	var tmp1 = 0;
	var tmp2 = 0;
	var result1 = 0;
	var result2 = 0;

    //获取异常的目的是防止存在整数的情况。
	try 
	{
		tmp1 = arg1.toString().split(".")[1].length;
	} 
	catch(e) 
	{
		tmp1 = 0;
	}

	try 
	{
		tmp2 = arg2.toString().split(".")[1].length;
	} 
	catch(e) 
	{
		tmp2 = 0;
	}

	result1 = Number(arg1.toString().replace(".", ""));
	result2 = Number(arg2.toString().replace(".", ""));
	
	return (result1 / result2) * Math.pow(10, tmp2 - tmp1);
}

Number.prototype.div = function(arg) {
	return accDiv(this, arg);
}

function accMul(arg1, arg2) 
{
	var tmp1 = 0;
	var tmp2 = 0;
	var result1 = 0;
	var result2 = 0;
	
	try 
	{
		tmp1 = arg1.toString().split(".")[1].length;
	} 
	catch (e) 
	{
        tmp1 = 0;
	}

	try 
	{
		tmp2 = arg2.toString().split(".")[1].length;
	} 
	catch (e) 
	{
		tmp2 = 0;
	}

	result1 = Number(arg1.toString().replace(".", ""));
	result2 = Number(arg2.toString().replace(".", ""));

	return (result1 * result2) / Math.pow(10, tmp1 + tmp2);
}

Number.prototype.mul = function(arg) {
	return accMul(this, arg);
}

function accAdd(arg1, arg2) 
{
	var tmp1 = 0;
	var tmp2 = 0;
	var tmp = 0;
	var result1 = 0;
	var result2 = 0;
	try 
	{
		tmp1 = arg1.toString().split(".")[1].length;
	} 
	catch (e) 
	{
		tmp1 = 0;
	}

	try 
	{
		tmp2 = arg2.toString().split(".")[1].length;
	} 
	catch (e) 
	{
		tmp2 = 0;
	}
	
	//arg1 + arg2 = ( result1/Math.pow(10,tmp1) ) + ( result2/Math.pow(10,tmp2) )
	//1.5+0.02 = 15/10 + 2/100
	//1.5+0.02 = 1.5*100/100 + 2*100/100
	tmp = Math.max(tmp1, tmp2);
	
    /**
     * 解决 319500-301418.09
     *        38890.91+116672.73+38890.91
     *        2.0-1.1
     * 对于javascript计算,直接*10或者*100也会出现精度错误,因此采用字符串的方式解决
     */
	
	result1 = arg1;
	result2 = arg2;
	
	var tmpStr = '';
	if (tmp>0)
	{
		tmpStr = arg1.toString().replace('.','');
		for (var i=0;i<tmp-tmp1;i++)
		{
			tmpStr += '0';
		}
		result1 = Number(tmpStr);

		tmpStr = arg2.toString().replace('.','');
		for (var i=0;i<tmp-tmp2;i++)
		{
			tmpStr += '0';
		}
		result2 = Number(tmpStr);
	}
	
	//return (arg1 * Math.pow(10, tmp) + arg2 * Math.pow(10, tmp)) / Math.pow(10, tmp);
	return (result1 + result2) / Math.pow(10, tmp);

}

Number.prototype.add = function(arg) {
	return accAdd(this, arg);
}

//减法的思路可以参照加法的思路。
function accSub(arg1, arg2) 
{
	var tmp1 = 0;
	var tmp2 = 0;
	var tmp = 0;
	var result1 = 0;
	var result2 = 0;
	
	try 
	{
		tmp1 = arg1.toString().split(".")[1].length;
	} 
	catch (e) 
	{
		tmp1 = 0;
	}

	try 
	{
		tmp2 = arg2.toString().split(".")[1].length;
	} 
	catch (e) 
	{
		tmp2 = 0;
	}

	tmp = Math.max(tmp1, tmp2);
	
    /**
     * 解决 319500-301418.09
     *        38890.91+116672.73+38890.91
     *        2.0-1.1
     * 对于javascript计算,直接*10或者*100也会出现精度错误,因此采用字符串的方式解决
     */
	result1 = arg1;
	result2 = arg2;
	
	var tmpStr = '';
	if (tmp>0)
	{

		tmpStr = arg1.toString().replace('.','');
		for (var i=0;i<tmp-tmp1;i++)
		{
			tmpStr += '0';
		}
		result1 = Number(tmpStr);

		tmpStr = arg2.toString().replace('.','');
		for (var i=0;i<tmp-tmp2;i++)
		{
			tmpStr += '0';
		}
		result2 = Number(tmpStr);
	}
	
	//return (arg1 * Math.pow(10, tmp) - arg2 * Math.pow(10, tmp)) / Math.pow(10, tmp);
	return (result1 - result2) / Math.pow(10, tmp);
}

Number.prototype.sub = function(arg) {
	return accSub(this, arg);
}
 
分享到:
评论

相关推荐

    解决javascript中的浮点数计算不精确问题

    在JavaScript编程中,...理解JavaScript浮点数计算的局限性并采用适当的策略,可以有效地应对和预防这类问题,保证代码的准确性和可靠性。在开发过程中,始终要对浮点数的运算结果保持警惕,并进行适当的验证和处理。

    JavaScript小数点精确计算

    首先,我们来理解JavaScript浮点数计算的原理。在JavaScript中,所有数字都是以64位的二进制浮点数形式存储的。由于二进制无法精确表示所有十进制小数,因此在转换过程中会出现误差,例如0.1 + 0.2 !== 0.3。这种...

    javaScript实现浮点数转十六进制字符

    JavaScript实现浮点数转十六进制字符的过程涉及到了浮点数的表示、IEEE 754标准、二进制与十六进制的转换等多个知识点。由于JavaScript直接使用浮点数转十六进制的功能实现并不直接,因此需要借助其他方法来实现。...

    precise-math.js:用于解决javascript中浮点数精确计算的问题

    precise-math.js用于解决javascript中浮点数精确计算的问题。目前只有三个方法,可以用于解决Javascript中金额计算的问题。PreciseMath.add(x1,x2) PreciseMath.sub(x1,x2) PreciseMath.mul(x1,x2)

    js浮点数处理转精确值

    还有一种叫做`BigInt`的数据类型,用于处理大整数,它可以避免整数溢出问题,但不适用于浮点数的精确计算。 在实际开发中,有时会使用库或自定义函数来处理浮点数的精确计算。例如,可以使用`decimal.js`这样的库,...

    js 浮点数加法运算

    javascript浮点数加法运算精确计算方法,能够有效避免无限循环小数的产生

    JavaScript 精确计算(2)

    在JavaScript编程语言中,精确计算是一项重要的需求,特别是在金融、科学计算或任何需要高精度数值操作的场景。由于JavaScript的内置Number类型使用浮点数表示,这可能导致在进行大数运算时出现微小的误差。标题...

    js浮点数精确计算(加、减、乘、除)

    代码如下:&lt;SPAN xss=removed&gt;//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。 //调用:accAdd(arg1,arg2) //返回值:arg1加上arg2的精确结果 ...

    JavaScript解决浮点数计算不准确问题的方法分析

    JavaScript中的浮点数计算不准确问题源于其内部的二进制表示方式,导致某些浮点数无法精确存储,从而在进行运算时出现误差。在计算机系统中,浮点数通常按照IEEE 754标准存储,双精度浮点数(JavaScript默认使用)的...

    JavaScript 浮点数运算 精度问题

    3. **使用库或内置方法**:有些JavaScript库,如`decimal.js`或`big.js`,专门用于处理高精度的浮点数运算,提供更精确的计算结果。 4. **使用toFixed()**:虽然`toFixed()`方法可以将数字格式化为指定位数的小数,...

    解决JS浮点数(小数)计算加减乘除的BUG

    总的来说,理解JavaScript浮点数计算的底层原理以及其可能导致的误差是至关重要的。通过采用适当的策略,如四舍五入、使用高精度库或调整比较方式,可以有效地解决这类问题,确保计算结果的准确性。在实际开发中,...

    详解JavaScript 浮点数运算的精度问题

    JavaScript中的浮点数运算精度问题是一个常见的编程挑战,由于JavaScript中的数字是以64位浮点数格式存储,根据IEEE 754标准,这导致在处理浮点数时...在需要精确计算的场景下,开发者应采取适当的措施来规避这些问题。

    javascript避免数字计算精度误差的方法详解.docx

    在JavaScript中处理浮点数计算时,精度误差是一个常见但又必须解决的问题。通过上述方法,我们可以有效地避免这类问题的发生,确保计算结果的准确性。不同的应用场景可能需要采用不同的策略,开发者应根据实际情况...

    JavaScript浮点数及运算精度调整详解

    JavaScript中的浮点数精度问题是由于IEEE-754标准的二进制浮点数表示法导致的,这种表示法无法准确表示所有十进制小数,特别是那些有无限循环二进制小数位的数值,例如0.1。在JavaScript中,所有的数字都以64位双...

    test_JS-数字精确计算_

    在JavaScript编程语言中,数字的精确计算确实是一个挑战,尤其是涉及到浮点数操作时。由于JavaScript内部使用IEEE 754标准存储和处理浮点数,这可能导致精度损失,尤其是在进行加减乘除等数学运算时。标题"test_JS-...

    JS浮点数字操作插件floatOPS.js

    在JavaScript编程中,...总结起来,floatOPS.js是一个专注于解决JavaScript中浮点数运算精度问题的插件,通过提供加减乘除四个方法,确保了在进行浮点数运算时的精度,对于需要精确计算的场景具有很高的实用价值。

Global site tag (gtag.js) - Google Analytics