|
@@ -1,225 +0,0 @@
|
|
|
-/**
|
|
|
|
|
- * Created by Tony on 2017/4/14.
|
|
|
|
|
- */
|
|
|
|
|
-const zeroString = (length: number) => {
|
|
|
|
|
- let result = '';
|
|
|
|
|
- for (let i = 0; i < length; i++) {
|
|
|
|
|
- result = result + '0';
|
|
|
|
|
- };
|
|
|
|
|
- return result;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const innerRoundTo = (num: number, digit: number) => {
|
|
|
|
|
- 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 = zeroString(-digit) + result;
|
|
|
|
|
- }
|
|
|
|
|
- // 当目标位数在小数点前,需要补齐后面的位数
|
|
|
|
|
- else if ((digit > 0) && (iLength < digit)) {
|
|
|
|
|
- result = result + 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)
|
|
|
|
|
-const floatToBin = (num: number): string => {
|
|
|
|
|
- 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;
|
|
|
|
|
-}
|
|
|
|
|
-const binToFloat = (bin: string): string => {
|
|
|
|
|
- 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;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const incMantissa = (bin: string): string => {
|
|
|
|
|
- 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 = zeroString(iLength - (i + 1));//bin.substring(i + 1, iLength);
|
|
|
|
|
- result = bin1 + num.toString() + bin2;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- };
|
|
|
|
|
- return result;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-const roundTo = (num: number, digit: number) => {
|
|
|
|
|
-
|
|
|
|
|
- // let str1 = me.floatToBin(num);
|
|
|
|
|
- // let str2 = me.incMantissa(str1);
|
|
|
|
|
- // return me.innerRoundTo( parseFloat(me.binToFloat(str2)), digit);
|
|
|
|
|
- return innerRoundTo(parseFloat(binToFloat(incMantissa(floatToBin(num)))), digit);
|
|
|
|
|
-}
|
|
|
|
|
-const isNumber = (obj: any) => {
|
|
|
|
|
- return obj === +obj;
|
|
|
|
|
-}
|
|
|
|
|
-const roundForObj = (obj: any, decimal: number) => {
|
|
|
|
|
-
|
|
|
|
|
- let value;
|
|
|
|
|
- if (isNumber(obj)) {
|
|
|
|
|
- value = roundTo(obj, -decimal)
|
|
|
|
|
- } else {
|
|
|
|
|
- value = roundTo(Number(obj), -decimal);
|
|
|
|
|
- }
|
|
|
|
|
- return value
|
|
|
|
|
-}
|
|
|
|
|
-const roundToString = (obj: any, decimal: number) => {
|
|
|
|
|
-
|
|
|
|
|
- let value;
|
|
|
|
|
- if (isNumber(obj)) {
|
|
|
|
|
- value = roundTo(obj, -decimal)
|
|
|
|
|
- } else {
|
|
|
|
|
- value = roundTo(Number(obj), -decimal);
|
|
|
|
|
- }
|
|
|
|
|
- return value.toFixed(decimal);
|
|
|
|
|
-}
|
|
|
|
|
-// isNumOrFormula:function (text: any) {
|
|
|
|
|
-// 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 = 0;
|
|
|
|
|
-// }
|
|
|
|
|
-// }
|
|
|
|
|
-// if(text == null || text == ''){
|
|
|
|
|
-// value = 0;
|
|
|
|
|
-// }
|
|
|
|
|
-// return value;
|
|
|
|
|
-// },
|
|
|
|
|
-const isDef = (v: any) => {
|
|
|
|
|
- return v !== undefined && v !== null;
|
|
|
|
|
-}
|
|
|
|
|
-//获取ID引用
|
|
|
|
|
-const getFIDArr = (exp: any) => {
|
|
|
|
|
- let fidRex = /@[\d,a-z,A-Z,-]{36}/g;
|
|
|
|
|
- let fidArr = exp.match(fidRex);
|
|
|
|
|
- return isDef(fidArr) ? fidArr : [];
|
|
|
|
|
-}
|
|
|
|
|
-export default {
|
|
|
|
|
- innerRoundTo,
|
|
|
|
|
- floatToBin,
|
|
|
|
|
- binToFloat,
|
|
|
|
|
- incMantissa,
|
|
|
|
|
- roundTo,
|
|
|
|
|
- isNumber,
|
|
|
|
|
- roundForObj,
|
|
|
|
|
- roundToString,
|
|
|
|
|
- isDef,
|
|
|
|
|
- getFIDArr
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|