|
@@ -5,6 +5,12 @@
|
|
|
*
|
|
|
* zhangyin 2018-02-28
|
|
|
* 采用重复一次四舍五入解决浮点精度误差后,10000次roundTo的时间为94毫秒。
|
|
|
+ *
|
|
|
+ * zhangyin 2018-04-28
|
|
|
+ * 因为js中的浮点数本身就有误差,经过运算后误差被放大,用加尾数的方式也不能消除。所以必须采用另一种思路。
|
|
|
+ * 考虑误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位。
|
|
|
+ * 原重复四舍五入的方法有缺陷,放弃。
|
|
|
+ * 10000次roundTo时间恢复到47毫秒
|
|
|
*/
|
|
|
|
|
|
let scMathUtil = {
|
|
@@ -68,7 +74,8 @@ let scMathUtil = {
|
|
|
let sResult2 = '';
|
|
|
if (fNum > 0){
|
|
|
// 双精度浮点数,尾数总长52位,因为第一位总是1,存储时已经被隐藏,所以有效位数为53位
|
|
|
- const floatLength = 53;
|
|
|
+ // 由于js未对浮点数做优化,所以在有运算的情况下,误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位
|
|
|
+ const floatLength = 50;
|
|
|
|
|
|
let iLength;
|
|
|
// js的bug,浮点数直接取小数可能不能获得精确值,只有转成字符串,截取字符串中的小数段
|
|
@@ -155,16 +162,10 @@ let scMathUtil = {
|
|
|
};
|
|
|
return result;
|
|
|
},
|
|
|
- reRoundTo: function(num, digit){
|
|
|
- let me = this;
|
|
|
- return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
|
|
|
- },
|
|
|
- // zhangyin 2018-02-28
|
|
|
- // 经过运算后的浮点数,误差可能更大,加尾数也不能消除。目前采用笨办法,将有效位数加一位再四舍五入一次,以消除浮点误差。
|
|
|
- // 此办法效率较低,没有别的更好办法时暂时用着
|
|
|
+
|
|
|
roundTo: function(num, digit){
|
|
|
let me = this;
|
|
|
- return me.reRoundTo(me.reRoundTo(num, digit - 1), digit);
|
|
|
+ return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
|
|
|
},
|
|
|
isNumber : function (obj) {
|
|
|
return obj === +obj;
|