fineui是帆软报表和BI产品线所使用的前端框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

222 lines
8.6 KiB

/**
* Created by zcf on 2017/3/1.
* 万恶的IEEE-754
* 使用字符串精确计算含小数加法、减法、乘法和10的指数倍除法,支持负数
*/
BI.AccurateCalculationModel = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.AccurateCalculationModel.superclass._defaultConfig.apply(this, arguments), {
baseCls: ""
});
},
_init: function () {
BI.AccurateCalculationModel.superclass._init.apply(this, arguments);
},
_getMagnitude: function (n) {
var magnitude = "1";
for (var i = 0; i < n; i++) {
magnitude += "0";
}
return BI.parseInt(magnitude);
},
_formatDecimal: function (stringNumber1, stringNumber2) {
if (stringNumber1.numDecimalLength === stringNumber2.numDecimalLength) {
return;
}
var magnitudeDiff = stringNumber1.numDecimalLength - stringNumber2.numDecimalLength;
if (magnitudeDiff > 0) {
var needAddZero = stringNumber2;
} else {
var needAddZero = stringNumber1;
magnitudeDiff = (0 - magnitudeDiff);
}
for (var i = 0; i < magnitudeDiff; i++) {
if (needAddZero.numDecimal === "0" && i === 0) {
continue;
}
needAddZero.numDecimal += "0";
}
},
_stringNumberFactory: function (num) {
var strNum = num.toString();
var numStrArray = strNum.split(".");
var numInteger = numStrArray[0];
if (numStrArray.length === 1) {
var numDecimal = "0";
var numDecimalLength = 0;
} else {
var numDecimal = numStrArray[1];
var numDecimalLength = numStrArray[1].length;
}
return {
numInteger: numInteger,
numDecimal: numDecimal,
numDecimalLength: numDecimalLength
};
},
_accurateSubtraction: function (num1, num2) {// num1-num2 && num1>num2
var stringNumber1 = this._stringNumberFactory(num1);
var stringNumber2 = this._stringNumberFactory(num2);
// 整数部分计算
var integerResult = BI.parseInt(stringNumber1.numInteger) - BI.parseInt(stringNumber2.numInteger);
// 小数部分
this._formatDecimal(stringNumber1, stringNumber2);
var decimalMaxLength = getDecimalMaxLength(stringNumber1, stringNumber2);
if (BI.parseInt(stringNumber1.numDecimal) >= BI.parseInt(stringNumber2.numDecimal)) {
var decimalResultTemp = (BI.parseInt(stringNumber1.numDecimal) - BI.parseInt(stringNumber2.numDecimal)).toString();
var decimalResult = addZero(decimalResultTemp, decimalMaxLength);
} else {// 否则借位
integerResult--;
var borrow = this._getMagnitude(decimalMaxLength);
var decimalResultTemp = (borrow + BI.parseInt(stringNumber1.numDecimal) - BI.parseInt(stringNumber2.numDecimal)).toString();
var decimalResult = addZero(decimalResultTemp, decimalMaxLength);
}
var result = integerResult + "." + decimalResult;
return BI.parseFloat(result);
function getDecimalMaxLength (num1, num2) {
if (num1.numDecimal.length >= num2.numDecimal.length) {
return num1.numDecimal.length;
}
return num2.numDecimal.length;
}
function addZero (resultTemp, length) {
var diff = length - resultTemp.length;
for (var i = 0; i < diff; i++) {
resultTemp = "0" + resultTemp;
}
return resultTemp;
}
},
_accurateAddition: function (num1, num2) {// 加法结合律
var stringNumber1 = this._stringNumberFactory(num1);
var stringNumber2 = this._stringNumberFactory(num2);
// 整数部分计算
var integerResult = BI.parseInt(stringNumber1.numInteger) + BI.parseInt(stringNumber2.numInteger);
// 小数部分
this._formatDecimal(stringNumber1, stringNumber2);
var decimalResult = (BI.parseInt(stringNumber1.numDecimal) + BI.parseInt(stringNumber2.numDecimal)).toString();
if (decimalResult !== "0") {
if (decimalResult.length <= stringNumber1.numDecimal.length) {
decimalResult = addZero(decimalResult, stringNumber1.numDecimal.length);
} else {
integerResult++;// 进一
decimalResult = decimalResult.slice(1);
}
}
var result = integerResult + "." + decimalResult;
return BI.parseFloat(result);
function addZero (resultTemp, length) {
var diff = length - resultTemp.length;
for (var i = 0; i < diff; i++) {
resultTemp = "0" + resultTemp;
}
return resultTemp;
}
},
_accurateMultiplication: function (num1, num2) {// 乘法分配律
var stringNumber1 = this._stringNumberFactory(num1);
var stringNumber2 = this._stringNumberFactory(num2);
// 整数部分计算
var integerResult = BI.parseInt(stringNumber1.numInteger) * BI.parseInt(stringNumber2.numInteger);
// num1的小数和num2的整数
var dec1Int2 = this._accurateDivisionTenExponent(BI.parseInt(stringNumber1.numDecimal) * BI.parseInt(stringNumber2.numInteger), stringNumber1.numDecimalLength);
// num1的整数和num2的小数
var int1dec2 = this._accurateDivisionTenExponent(BI.parseInt(stringNumber1.numInteger) * BI.parseInt(stringNumber2.numDecimal), stringNumber2.numDecimalLength);
// 小数*小数
var dec1dec2 = this._accurateDivisionTenExponent(BI.parseInt(stringNumber1.numDecimal) * BI.parseInt(stringNumber2.numDecimal), (stringNumber1.numDecimalLength + stringNumber2.numDecimalLength));
return this._accurateAddition(this._accurateAddition(this._accurateAddition(integerResult, dec1Int2), int1dec2), dec1dec2);
},
_accurateDivisionTenExponent: function (num, n) {// num/10^n && n>0
var stringNumber = this._stringNumberFactory(num);
if (stringNumber.numInteger.length > n) {
var integerResult = stringNumber.numInteger.slice(0, (stringNumber.numInteger.length - n));
var partDecimalResult = stringNumber.numInteger.slice(-n);
} else {
var integerResult = "0";
var partDecimalResult = addZero(stringNumber.numInteger, n);
}
var result = integerResult + "." + partDecimalResult + stringNumber.numDecimal;
return BI.parseFloat(result);
function addZero (resultTemp, length) {
var diff = length - resultTemp.length;
for (var i = 0; i < diff; i++) {
resultTemp = "0" + resultTemp;
}
return resultTemp;
}
},
accurateSubtraction: function (num1, num2) {
if (num1 >= 0 && num2 >= 0) {
if (num1 >= num2) {
return this._accurateSubtraction(num1, num2);
}
return -this._accurateSubtraction(num2, num1);
}
if (num1 >= 0 && num2 < 0) {
return this._accurateAddition(num1, -num2);
}
if (num1 < 0 && num2 >= 0) {
return -this._accurateAddition(-num1, num2);
}
if (num1 < 0 && num2 < 0) {
if (num1 >= num2) {
return this._accurateSubtraction(-num2, -num1);
}
return this._accurateSubtraction(-num1, -num2);
}
},
accurateAddition: function (num1, num2) {
if (num1 >= 0 && num2 >= 0) {
return this._accurateAddition(num1, num2);
}
if (num1 >= 0 && num2 < 0) {
return this.accurateSubtraction(num1, -num2);
}
if (num1 < 0 && num2 >= 0) {
return this.accurateSubtraction(num2, -num1);
}
if (num1 < 0 && num2 < 0) {
return -this._accurateAddition(-num1, -num2);
}
},
accurateMultiplication: function (num1, num2) {
if (num1 >= 0 && num2 >= 0) {
return this._accurateMultiplication(num1, num2);
}
if (num1 >= 0 && num2 < 0) {
return -this._accurateMultiplication(num1, -num2);
}
if (num1 < 0 && num2 >= 0) {
return -this._accurateMultiplication(-num1, num2);
}
if (num1 < 0 && num2 < 0) {
return this._accurateMultiplication(-num1, -num2);
}
},
accurateDivisionTenExponent: function (num1, n) {
if (num1 >= 0) {
return this._accurateDivisionTenExponent(num1, n);
}
return -this._accurateDivisionTenExponent(-num1, n);
}
});