javascript 浮点计算
这几天在进行浮点运算时候遇到一个问题,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代码,在这里和大家分享下:
1 <script type="text/javascript"> 2 /** 3 * 左补齐字符串 4 * @param nSize 要补齐的长度 5 * @param ch 要补齐的字符 6 * @return 7 */ 8 String.prototype.padLeft = function (nSize, ch) { 9 var len = 0; 10 var s = this ? this : ""; 11 ch = ch ? ch : '0'; // 默认补0 12 len = s.length; 13 while (len < nSize) { 14 s = ch + s; 15 len++; 16 } 17 return s; 18 } 19 20 /** 21 * 右补齐字符串 22 * @param nSize 要补齐的长度 23 * @param ch 要补齐的字符 24 * @return 25 */ 26 String.prototype.padRight = function (nSize, ch) { 27 var len = 0; 28 var s = this ? this : ""; 29 ch = ch ? ch : '0'; // 默认补0 30 len = s.length; 31 while (len < nSize) { 32 s = s + ch; 33 len++; 34 } 35 return s; 36 } 37 /** 38 * 左移小数点位置(用于数学计算,相当于除以Math.pow(10,scale)) 39 * @param scale 要移位的刻度 40 * @return 41 */ 42 String.prototype.movePointLeft = function (scale) { 43 var s, s1, s2, ch, ps, sign; 44 ch = '.'; 45 sign = ''; 46 s = this ? this : ""; 47 if (scale <= 0) return s; 48 ps = s.split('.'); 49 s1 = ps[0] ? ps[0] : ""; 50 s2 = ps[1] ? ps[1] : ""; 51 if (s1.slice(0, 1) == '-') { 52 s1 = s1.slice(1); 53 sign = '-'; 54 } 55 if (s1.length <= scale) { 56 ch = "0."; 57 s1 = s1.padLeft(scale); 58 } 59 return sign + s1.slice(0, -scale) + ch + s1.slice(-scale) + s2; 60 } 61 /** 62 * 右移小数点位置(用于数学计算,相当于乘以Math.pow(10,scale)) 63 * @param scale 要移位的刻度 64 * @return 65 */ 66 String.prototype.movePointRight = function (scale) { 67 var s, s1, s2, ch, ps; 68 ch = '.'; 69 s = this ? this : ""; 70 71 if (scale <= 0) return s; 72 ps = s.split('.'); 73 s1 = ps[0] ? ps[0] : ""; 74 s2 = ps[1] ? ps[1] : ""; 75 if (s2.length <= scale) { 76 ch = ''; 77 s2 = s2.padRight(scale); 78 } 79 return s1 + s2.slice(0, scale) + ch + s2.slice(scale, s2.length); 80 } 81 /** 82 * 移动小数点位置(用于数学计算,相当于(乘以/除以)Math.pow(10,scale)) 83 * @param scale 要移位的刻度(正数表示向右移;负数表示向左移动;0返回原值) 84 * @return 85 */ 86 String.prototype.movePoint = function (scale) { 87 if (scale >= 0) 88 return this.movePointRight(scale); 89 else 90 return this.movePointLeft(-scale); 91 } 92 93 Number.prototype.toFixed = function (scale) { 94 var s, s1, s2, start; 95 s1 = this + ""; 96 start = s1.indexOf("."); 97 s = s1.movePoint(scale); 98 if (start >= 0) { 99 s2 = Number(s1.substr(start + scale + 1, 1)); 100 if (s2 >= 5 && this >= 0 || s2 < 5 && this < 0) { 101 s = Math.ceil(s); 102 } else { 103 s = Math.floor(s); 104 } 105 } 106 return s.toString().movePoint(-scale); 107 } 108 </script>
加入上述代码后
alert(Number(1.005).toFixed(2)); //输出 1.01
如果要进行浮点计算 就要使用movePoint方法进行升值操作后再降值得出精确结果!