您的位置:首页 > Web前端 > JavaScript

javaScript中Float精度计算

2015-05-25 16:15 113 查看
在项目中做了一个计算统计值的部分,实现过程是通过 javaScript 进行累加的。在测试时出现了一个很乖的问题,在此记录一下。

1. 问题背景

项目中有一个表格字段,数据类型是float的,在数据库中均以Decimal(10,2)的格式保存(也即有效数字为10,小数点为两位)。现在,要对该字段进行累加统计。

2. JavaScript实现

考虑到JavaScript中的数据是无类型的自动判断,因此没有多想,直接将这个字段循环累加,代码如下:

// 统计UFP值
RequireCount.prototype.addUFP = function(value) {
	this.count_ufp += value;
};
// 统计US总值
RequireCount.prototype.addUS = function(value) {
	this.count_US += value;
};


本以为很简单,但是在显示计算结果时,出现了让我感到纳闷的一幕:



数据库中的数据全部都是小数点为两位的数据,怎么会出现这么长的小数点位数(50.68000000000001),也不该出现.00000000001吧?

3. 查找资料

在JavaScript中,数值(浮点型)数据在存储时并不区分Number还是Float型,而是全部按照Float的类型来进行存储。存储方式为:整形部分的长度为10,小数部分位数为16;如果最后一位小数为0则用1代替(这个地方很难理解,为啥用1代替最后一位,具体解释是用1来代替有效数字位数)

4. 问题解释

在统计过程中,如果出现了两者相加出现整数(也即后面小数点部分都满整了,比如,3.45 + 2.55 = 6.00),这时,计算结果将代替为:6.0000000000000001而不是,6.00。因为根据以上资料的规定就是这么个意思。是不是很奇怪的规定





,不知道为什么这么规定,需要以后深入了解。

5. 解决方式(根据目前情况,并非正确解决方案,请勿模仿

因为,项目中的数据量不是很大,按照精度问题来说,后面的一大片零头不会影响前面的数据结果,故而使用了 toFixed方法截取所需要的部分:

<span style="font-size:18px;">var floatTest = 5.6849392174

var needFloat = loatTest.toFixed(2)</span>
虽然,不是正确的解决方案,但是针对目前情况来讲,是一个适用的“解决方案”


6. 问题延展及终极解决方案

加法会出现此问题,我们自然就会想到减法运算,然后就是乘除运算。

对于乘法,这不能这么“大意大胆”的使用上面的方式,毕竟乘法可不是一点点的累加了,可以说是:失之毫厘谬以千里啊。

6.1 加法:

function add(value1, value2) {
	var r1, r2, m;
	try {
		r1 = value1.toString().split(".")[1].length;
	} catch (e) {
		r1 = 0;
	}
	try {
		r2 = value2.toString().split(".")[1].length;
	} catch (e) {
		r2 = 0;
	}
	m = Math.pow(10, Math.max(r1, r2));
	return (value1 * m + value2 * m) / m;
}


6.2 减法:

function Subtr(value1, value2) {
	var r1, r2, m, n;
	try {
		r1 = value1.toString().split(".")[1].length;
	} catch (e) {
		r1 = 0;
	}
	try {
		r2 = value2.toString().split(".")[1].length;
	} catch (e) {
		r2 = 0;
	}
	m = Math.pow(10, Math.max(r1, r2));
	// 动态控制精度长度
	n = (r1 >= r2) ? r1 : r2;
	return ((value1 * m - value2 * m) / m).toFixed(n);
}


6.3 乘法:

function multiple(value1, value2) {
	var m = 0, s1 = value1.toString(), s2 = value2.toString();
	try {
		m += s1.split(".")[1].length;
	} catch (e) {
	}
	try {
		m += s2.split(".")[1].length;
	} catch (e) {
	}
	return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
}


6.4 除法:

function divider(value1, value2) {
	var t1 = 0, t2 = 0, r1, r2;
	try {
		t1 = value1.toString().split(".")[1].length;
	} catch (e) {
	}
	try {
		t2 = value2.toString().split(".")[1].length;
	} catch (e) {
	}
	with (Math) {
		r1 = Number(value1.toString().replace(".", ""));
		r2 = Number(value2.toString().replace(".", ""));
		return (r1 / r2) * pow(10, t2 - t1);
	}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: