/** * 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); } });