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

javascript 浮点计算

2013-03-26 19:43 190 查看
这几天在进行浮点运算时候遇到一个问题,toFixd()给出的四舍五入值“几率性”的出现错误!

我们举个列子 :

  alert(0.1+0.2); //输出 0.30000000000000004

  alert(Number(1.005).toFixed(2)); //输出 1.00

  alert(Number(1.006).toFixed(2)); //输出 1.01

从上面我们可以看到,只有最后一个是正确的。为什么会这样呢?

由于计算机是用二进制来存储和处理数字,不能精确表示浮点数,而js中没有相应的封装类来处理浮点数运算,直接计算会导致运算精度丢失。

0.1在js里面就需要被表示成 1/16+1/32+.......转换成二进制就是0.00011001100110011无限循环

0.5在js里面就可以直接表示成1/2 转换成二进制就是0.01

所几率性出错就可以被解释了,可以被2的负多少次方精确表示出来的是不会丢失精度。如果不能被表示则会丢失精度!

下面是从网上找到的一个覆盖toFixed()的js代码,在这里和大家分享下:

<script type="text/javascript">
/**
* 左补齐字符串
* @param nSize 要补齐的长度
* @param ch 要补齐的字符
* @return
*/
String.prototype.padLeft = function (nSize, ch) {
var len = 0;
var s = this ? this : "";
ch = ch ? ch : '0'; // 默认补0
len = s.length;
while (len < nSize) {
s = ch + s;
len++;
}
return s;
}

/**
* 右补齐字符串
* @param nSize 要补齐的长度
* @param ch 要补齐的字符
* @return
*/
String.prototype.padRight = function (nSize, ch) {
var len = 0;
var s = this ? this : "";
ch = ch ? ch : '0'; // 默认补0
len = s.length;
while (len < nSize) {
s = s + ch;
len++;
}
return s;
}
/**
* 左移小数点位置(用于数学计算,相当于除以Math.pow(10,scale))
* @param scale 要移位的刻度
* @return
*/
String.prototype.movePointLeft = function (scale) {
var s, s1, s2, ch, ps, sign;
ch = '.';
sign = '';
s = this ? this : "";
if (scale <= 0) return s;
ps = s.split('.');
s1 = ps[0] ? ps[0] : "";
s2 = ps[1] ? ps[1] : "";
if (s1.slice(0, 1) == '-') {
s1 = s1.slice(1);
sign = '-';
}
if (s1.length <= scale) {
ch = "0.";
s1 = s1.padLeft(scale);
}
return sign + s1.slice(0, -scale) + ch + s1.slice(-scale) + s2;
}
/**
* 右移小数点位置(用于数学计算,相当于乘以Math.pow(10,scale))
* @param scale 要移位的刻度
* @return
*/
String.prototype.movePointRight = function (scale) {
var s, s1, s2, ch, ps;
ch = '.';
s = this ? this : "";

if (scale <= 0) return s;
ps = s.split('.');
s1 = ps[0] ? ps[0] : "";
s2 = ps[1] ? ps[1] : "";
if (s2.length <= scale) {
ch = '';
s2 = s2.padRight(scale);
}
return s1 + s2.slice(0, scale) + ch + s2.slice(scale, s2.length);
}
/**
* 移动小数点位置(用于数学计算,相当于(乘以/除以)Math.pow(10,scale))
* @param scale 要移位的刻度(正数表示向右移;负数表示向左移动;0返回原值)
* @return
*/
String.prototype.movePoint = function (scale) {
if (scale >= 0)
return this.movePointRight(scale);
else
return this.movePointLeft(-scale);
}

Number.prototype.toFixed = function (scale) {
var s, s1, s2, start;
s1 = this + "";
start = s1.indexOf(".");
s = s1.movePoint(scale);
if (start >= 0) {
s2 = Number(s1.substr(start + scale + 1, 1));
if (s2 >= 5 && this >= 0 || s2 < 5 && this < 0) {
s = Math.ceil(s);
} else {
s = Math.floor(s);
}
}
return s.toString().movePoint(-scale);
}
</script>


加入上述代码后

alert(Number(1.005).toFixed(2)); //输出 1.01

如果要进行浮点计算 就要使用movePoint方法进行升值操作后再降值得出精确结果!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: