浏览代码

同步 scMathUtil

zhongzewei 7 年之前
父节点
当前提交
262cff6f20
共有 2 个文件被更改,包括 101 次插入7 次删除
  1. 100 7
      public/web/scMathUtil.js
  2. 1 0
      web/maintain/std_glj_lib/js/glj.js

+ 100 - 7
public/web/scMathUtil.js

@@ -1,5 +1,7 @@
 /**
  * Created by jimiz on 2017/3/28.
+ * 经验证:10000次四舍五入,用num.toFixed为15毫秒,用roundTo为47毫秒,速度低一些,但可以接受
+ * 另:经手工验证,用num.toString(2)将十进制浮点数转换为二进制浮点数时,最后一位有错误的情况出现,例子(10.0311)
  */
 
 let scMathUtil = {
@@ -7,18 +9,93 @@ let scMathUtil = {
         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) {
-        return num.toString(2);
+        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位
+            const floatLength = 53;
+
+            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;
@@ -60,13 +137,7 @@ let scMathUtil = {
         let result = bin;
         let iDot = bin.indexOf('.');
         if (iDot < 0){return result};
-        // 二进制浮点数带小数位数最大长度
-        let floatLength = 53;
         let iLength = bin.length;
-        // 长度小于53说明该二进制数尾数长度小于Double类型限制,未被截断,无需进位
-        if (iLength < floatLength) {
-            return result;
-        }
         iLength = bin.length;
         for (let i = iLength - 1; i > iDot; i--){
             let num = Number(bin[i]);
@@ -84,5 +155,27 @@ let scMathUtil = {
     roundTo: function(num, digit){
         let me = this;
         return me.innerRoundTo(me.binToFloat(me.incMantissa(me.floatToBin(num))), digit);
+    },
+    isNumber : function (obj) {
+        return obj === +obj;
+    },
+    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);
     }
+};
+
+Number.prototype.toDecimal = function (ADigit) {
+    //return parseFloat(this.toFixed(ADigit));
+    digit = (ADigit && 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);
 };

+ 1 - 0
web/maintain/std_glj_lib/js/glj.js

@@ -523,6 +523,7 @@ let repositoryGljObj = {
                         rObj.basePrice = 0;
                     }
                     rObj.basePrice = !isNaN(parseFloat(rObj.basePrice)) && (rObj.basePrice && typeof rObj.basePrice !== 'undefined') ? scMathUtil.roundTo(parseFloat(rObj.basePrice), -2) : 0;
+                    console.log(rObj.basePrice);
                     addArr.push(rObj);
                 }
             }