| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 | 
							- /**
 
-  * Created by jimiz on 2017/3/28.
 
-  * 经验证:10000次四舍五入,用num.toFixed为15毫秒,用roundTo为47毫秒,速度低一些,但可以接受
 
-  * 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
 
-  *
 
-  * zhangyin 2018-02-28
 
-  * 采用重复一次四舍五入解决浮点精度误差后,10000次roundTo的时间为94毫秒。
 
-  *
 
-  * zhangyin 2018-04-28
 
-  * 因为js中的浮点数本身就有误差,经过运算后误差被放大,用加尾数的方式也不能消除。所以必须采用另一种思路。
 
-  * 考虑误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位。
 
-  * 原重复四舍五入的方法有缺陷,放弃。
 
-  * 10000次roundTo时间恢复到47毫秒
 
-  */
 
- let scMathUtil = {
 
-     innerRoundTo: function(num, digit){
 
-         let lFactor = Math.pow(10, digit);
 
-         let fOffSet = 0.5;
 
-         let sign = '';
 
-         // 处理符号
 
-         if (num < 0){
 
-             sign = '-';
 
-             num = Math.abs(num);
 
-         }
 
-         // 计算
 
-         let result = Math.floor((num / lFactor) + fOffSet).toString();
 
-         let iLength = result.length;
 
-         // 因为数值被转为整数计算,当目标位数在小数点后,且数值小于0,需要补齐前面的位数
 
-         if (iLength < -digit){
 
-             result = this.zeroString(-digit) + result;
 
-         }
 
-         // 当目标位数在小数点前,需要补齐后面的位数
 
-         else if ((digit > 0) && (iLength < digit)){
 
-             result = result + this.zeroString(digit);
 
-         }
 
-         iLength = result.length;
 
-         // 获得小数点前的数字
 
-         let r1 = result.substring(0, iLength + digit);
 
-         // 获得小数点后的数字
 
-         let r2 = result.substring(iLength + digit, iLength);
 
-         // 拼出完整结果
 
-         return Number(sign + r1 + '.' + r2);
 
-     },
 
-     // 原来直接用num.toString(2),如果小数段最后位数是0,会被舍掉,导致进位计算bug
 
-     // 改为自己计算二进制,固定为53位。
 
-     // 经验证速度没有差别
 
-     // 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
 
-     floatToBin: function(num) {
 
-         let sign = '';
 
-         let dNum = num;
 
-         // 符号位
 
-         if (num < 0) {
 
-             sign = '-';
 
-             dNum = -num;
 
-         };
 
-         // 解析整数段
 
-         let iNum = Math.floor(dNum);
 
-         let iFactor;
 
-         let sResult1 = '';
 
-         // 计算二进制整数段
 
-         while (iNum > 0){
 
-             iFactor = iNum % 2;
 
-             iNum = Math.floor(iNum / 2);
 
-             sResult1 = iFactor + sResult1;
 
-         }
 
-         // 判断是否有整数段
 
-         let bIntZero = sResult1 === '';
 
-         if (bIntZero){
 
-             sResult1 = '0';
 
-         }
 
-         // 解析小数段
 
-         let fNum = dNum - Math.floor(dNum);
 
-         let sResult2 = '';
 
-         if (fNum > 0){
 
-             // 双精度浮点数,尾数总长52位,因为第一位总是1,存储时已经被隐藏,所以有效位数为53位
 
-             // 由于js未对浮点数做优化,所以在有运算的情况下,误差会被放大,因此放弃一位有效位数来消除误差,二进制有效位数50位,十进制有效位数15位
 
-             const floatLength = 50;
 
-             let iLength;
 
-             // js的bug,浮点数直接取小数可能不能获得精确值,只有转成字符串,截取字符串中的小数段
 
-             let sNum = dNum.toString(10);
 
-             let iDot = sNum.indexOf('.');
 
-             sNum = '0' + sNum.substring(iDot, sNum.length);
 
-             fNum = Number(sNum);
 
-             // 有整数段,则小数位数为全部位数-整数位数
 
-             if (!bIntZero){
 
-                 iLength = floatLength - sResult1.length;
 
-             }
 
-             else{
 
-                 iLength = floatLength;
 
-             }
 
-             // 计算二进制小数段
 
-             while (iLength > 0){
 
-                 fNum = fNum * 2;
 
-                 iFactor = Math.floor(fNum);
 
-                 fNum = fNum % 1;
 
-                 sResult2 = sResult2 + iFactor;
 
-                 if (iFactor > 0){
 
-                     bIntZero = false;
 
-                 }
 
-                 if (bIntZero && (iFactor === 0)){
 
-                     continue;
 
-                 }
 
-                 iLength--;
 
-             }
 
-         }
 
-         return sign + sResult1 + '.' + sResult2;
 
-     },
 
-     binToFloat: function(bin) {
 
-         let result = 0;
 
-         let iLength = bin.length;
 
-         let sign = '';
 
-         if (iLength > 0 && bin[0]==='-'){
 
-             sign = '-';
 
-             bin = bin.substring(1, iLength);
 
-         }
 
-         iLength = bin.length;
 
-         let iDot = bin.indexOf('.');
 
-         if (iDot >= 0) {
 
-             for (let i = 0; i < iLength; i++) {
 
-                 let num = Number(bin[i]);
 
-                 let idx = iDot - i;
 
-                 if (idx === 0) {
 
-                     continue
 
-                 };
 
-                 if (idx > 0) {
 
-                     idx -= 1
 
-                 };
 
-                 let r = Math.pow(2, idx);
 
-                 result += num * r;
 
-             }
 
-         }
 
-         else {
 
-             result = parseInt(bin, 2);
 
-         };
 
-         return sign + result;
 
-     },
 
-     zeroString: function(length){
 
-         let result = '';
 
-         for (let i = 0; i < length; i++){
 
-             result = result + '0';
 
-         };
 
-         return result;
 
-     },    
 
-     incMantissa: function(bin){
 
-         let result = bin;
 
-         let iDot = bin.indexOf('.');
 
-         if (iDot < 0){return result};
 
-         let iLength = bin.length;
 
-         iLength = bin.length;
 
-         for (let i = iLength - 1; i > iDot; i--){
 
-             let num = Number(bin[i]);
 
-             if (num === 0){
 
-                 num = 1;
 
-                 let bin1 = bin.substring(0, i);
 
-                 let bin2 = this.zeroString(iLength - (i + 1));//bin.substring(i + 1, iLength);
 
-                 result = bin1 + num.toString() + bin2;
 
-                 break;
 
-             }
 
-         };
 
-         return result;
 
-     },
 
-     roundTo: function(num, digit){
 
-         let me = this;
 
-         return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
 
-     },
 
-     isNumber : function (obj) {
 
-         return obj === +obj;
 
-     },
 
-     roundForObj:function(obj,decimal){
 
-         let me = this;
 
-         let value;
 
-         if(me.isNumber(obj)){
 
-             value = me.roundTo(obj,-decimal)
 
-         }else {
 
-             value = me.roundTo(Number(obj),-decimal);
 
-         }
 
-         return value
 
-     },
 
-     roundToString:function(obj,decimal){
 
-         let me = this;
 
-         let value;
 
-         if(me.isNumber(obj)){
 
-             value = me.roundTo(obj,-decimal)
 
-         }else {
 
-             value = me.roundTo(Number(obj),-decimal);
 
-         }
 
-         return value.toFixed(decimal);
 
-     },
 
-     isNumOrFormula:function (text) {
 
-         let value = Number(text);
 
-         if(value ==0 ) return value;
 
-         if (!value) {
 
-             try {
 
-                 let exp = new Expression('');
 
-                 exp.Expression(text);
 
-                 value = Number(exp.Evaluate());
 
-             } catch (error) {
 
-                 value = null;
 
-             }
 
-         }
 
-         if(text==null||text==""){
 
-             value = null;
 
-         }
 
-         return value;
 
-     },
 
-     isDef:function (v) {
 
-         return v !== undefined && v !== null;
 
-     },
 
-     //获取ID引用
 
-     getFIDArr: function (exp) {
 
-         let fidRex = /@[\d,a-z,A-Z,-]{36}/g;
 
-         let fidArr = exp.match(fidRex);
 
-         return this.isDef(fidArr) ? fidArr : [];
 
-     }
 
- };
 
- Number.prototype.toDecimal = function (ADigit) {
 
-     //return parseFloat(this.toFixed(ADigit));
 
-     digit = ((ADigit!=null||ADigit!=undefined) && typeof(ADigit) === 'number' && Number.isInteger(ADigit) && ADigit >= 0) ? -ADigit : -2;
 
-     // var s = scMathUtil.roundTo(this, digit);
 
-     // console.log('Number: ' + this + '   Digit: ' + digit + '    Result: ' + s);
 
-     // return parseFloat(s);
 
-     return scMathUtil.roundTo(this, digit);
 
- };
 
 
  |