As I have noted in the main page for XNS, JavaScript cannot accurately handle all fractions of a number. However, it can and does accurately handle integers in the IEEE 754 binary floating point system. The XNS BigDecimal() script takes advantage of this fact by breaking up a given number A into sections of digits, which have no decimal point in them. These sections are therefore integers by definition.
A valid XNS BigDecimal() number takes the format:
* (-1 or 1), with j being a positive integer and , and
The idea is A is the finished number. Suppose j = 1. Then the number is 3.1415926535... Note the alternation between the bold-faced and the normal characters. Each section indicates a value of digits combined, which is itself a valid integer. In fact, with the exception of the decimal point and the minus sign, all such sections of decimal numbers are nonnegative integers.
Now suppose instead j = 4. Then the number is 3.1415926535... It still matches the definition of a decimal number, but at the same time we have discrete blocks of digits within the number.
You may notice in the above examples that the first digit to the left of the decimal point is part of the same section as the first digit to the right. The decimal point is a fundamental feature of any number, and its position must be exactly determined. So suppose we rearranged our digits such that the decimal point was between sections instead of embedded in one. In this scenario, is 3.1415926535...
With this arrangement of digits, we can then take each distinct section of digits and make it an element of an array: [3, 1415, 9265, 3500] represents the sequence of digits for to 11 digits. We note the decimal point is after the 0 section of the array [3], and the number is not a negative number.
These three facts: the array of sectioned digits, the placement of the decimal, and whether or not the value is negative, are all which are required to define a decimal number. Thus, the three facts can be collected as properties of a BigDecimal() number type.
XNS has already defined a standard for
BigDecimal.prototype.isNegative
as a function. Therefore, we
only need two additional properties: this.digitArray
to hold the
array of digit sections, and this.decPtAfter
to specify where
the decimal point resides.
As accurate as you want them to be. Because the arithmetic processes do not themselves depend on the number of sections in the BigDecimal(), you can have as many sections, and thus as many digits, as you desire.
The BigDecimal() script sets a default maximum length of approximately 100
digits, however. This value, reflected via the
BigDecimal.maxDigits
property, guarantees at least 100
significant digits, when such is needed.
As for within each section of digits, I have set the maximum number of digits per section at 6. The reason is simple: 999999 * 999999 = 999998000001, which has precisely 12 digits. Allowing for multiples of this number, we can safely reach 16 digits per section, before JavaScript's accuracy begins to falter. (To reach 17 digits, you'd need at least 10,000 instances of 9999999 * 9999999 entering into that section: a highly unlikely event except under extreme conditions.)
In the process of arithmetic operations, a BigDecimal() number may be constructed which starts out valid, but quickly becomes invalid. For instance, we may have a digit section within the number which is negative. Or we may have a digit section which exceeds the maximum section value permissible. These are the cost of doing business with BigDecimal() numbers, and the BigDecimal() script provides two functions to convert an invalid BigDecimal() number into a valid one.
The first is the carryCompact()
method of BigDecimal() number
objects. It checks for several things:
The second is the compactNum()
method of BigDecimal() number
objects. It calls this.carryCompact()
twice: once at the
beginning of this.compactNum()
, and once at the end. The reason
for this is simple. the compactNum()
function is specifically
designed for rounding operations, in case the BigDecimal() number exceeds the
maximum preset number of digits. (0.99999... == 1.0) This function takes
several steps:
this.digitArray
to have no spare
sections.All four arithmetic methods call compactNum()
on the
BigDecimal() numbers they return, just prior to returning those numbers.
The rules are pretty simple:
NaN
, return
Number.NaN
.In elementary addition and subtraction, we are taught to line up the
decimal points, and add or subtract the digits that line up. The same thing
applies to addition and subtraction of BigDecimals(). (The two processes are
so similar, in fact, that the subtract()
method truly calls the
add()
method, with a special second argument.)
Given two BigDecimal() numbers A
and B
, both
positive and being added together, the following takes place:
C
as a clone of A
.offset = A.decPtAfter - B.decPtAfter
k
in B
, C.digitArray[k
+ offset] += B.digitArray[k]
For subtraction, we invert the sign (+=
becomes
-=
). When B
is a negative number, we invert the
sign again.
In elementary multiplication, we are also taught to shift the decimal
point appropriately. Again, BigDecimal() does this, sort of. Given two
BigDecimal() numbers A
and B
, and a response
C
,. we find C.decPtAfter == A.decPtAfter +
B.decPtAfter
.
As for performing the actual multiplication, we rely on a basic algebra theorem:
(a + b)(c + d) == ac + ad + bc + bd
Many English-speaking people call this "FOIL": First, Outer, Inner, Last.
In BigDecimal() numbers, b
and d
may be later
sections in the respective digitArray
properties than
a
and c
, and we shift them down further.
Given two BigDecimal() numbers A
and B
, both
positive and being multiplied together, the following takes place:
C
with a value of 0.C.decPtAfter == A.decPtAfter + B.decPtAfter
h
in A
and for each section
k
in B
, C.digitArray[h + k] +=
A.digitArray[h] * B.digitArray[k]
Here, we take a diversion from typical arithmetic, for reasons of practicality. I actually cover this in a separate document (involving a fair amount of mathematical theory). The document is titled "Division of BigDecimals". The source code is listed below.
function BigDecimal() { if (arguments.length > 0) { var numString = arguments[0] } else { this.isNegative = returnFalse this.digitArray = [0] this.decPtAfter = 0 return this } if (typeof numString.xnsType == "undefined") { return new XNS_NaN() } switch (numString.xnsType) { case "NaN": return new XNS_NaN() case "Infinity": return new XNS_Infinity() case "-Infinity": return new XNS_NEG_Infinity() case "BigDecimal": this.decPtAfter = numString.decPtAfter * 1 this.digitArray = numString.digitArray.join().split(",") if (numString.isNegative()) { this.isNegative = returnTrue } else { this.isNegative = returnFalse } break; case "Number": var source = numString.toString() // we want a pure string switch (source) { case "NaN": return new XNS_NaN() case "Infinity": return new XNS_Infinity() case "-Infinity": return new XNS_NEG_Infinity() break; } if (isNaN(source)) { return new XNS_NaN() break; } if (source.charAt(0) == "-") { this.isNegative = returnTrue source = source.substr(1) } else { this.isNegative = returnFalse } if (source.indexOf(".") == -1) { source+="." } if (source.charAt(0) == ".") { source = "0" + source } var wholeNum = source.substr(0, source.indexOf(".")) var decimals = source.substr(source.indexOf(".") + 1) var wholeNum_shift = wholeNum.length % BigDecimal.sectDigits var digitArray = [] if (wholeNum_shift != 0) { digitArray[0] = wholeNum.substr(0, wholeNum_shift) } digitArray = digitArray.concat(wholeNum.substr(wholeNum_shift).match(BigDecimal.regexpSplit)) if (digitArray[digitArray.length - 1] == null) { digitArray.length-- } var decPtAfter = digitArray.length - 1 var decimal_back = decimals.length % BigDecimal.sectDigits digitArray = digitArray.concat(decimals.match(BigDecimal.regexpSplit)); if (digitArray[digitArray.length - 1] == null) { digitArray.length-- } if (decimal_back != 0) { digitArray[digitArray.length] = decimals.substr(decimals.length-decimal_back) while (digitArray[digitArray.length - 1].length < BigDecimal.sectDigits) { digitArray[digitArray.length - 1] += "0" } } this.digitArray = digitArray this.decPtAfter = decPtAfter this.compactNum() // automatically clean up number to restrict BigDecimal value break; // end case "Number" for numString.xnsType default: return new XNS_NaN() } // return global variables return this }
BigDecimal.sectDigits = 6 BigDecimal.maxDigits = 100 BigDecimal.maxSection = Math.pow(10, BigDecimal.sectDigits) BigDecimal.totalSections = Math.ceil(BigDecimal.maxDigits / BigDecimal.sectDigits) + 1 BigDecimal.addZeroes = BigDecimal.maxSection.toString().substr(1) BigDecimal.regexpSplit = new RegExp("\\d{" + BigDecimal.sectDigits + "}", "g");
BigDecimal.prototype.xnsType = "BigDecimal"
BigDecimal.prototype.xnsVersion = "0.5"
BigDecimal.prototype.isReal = returnTrue
BigDecimal.prototype.isDecimal = returnTrue
BigDecimal.prototype.isRational = returnTrue
BigDecimal.prototype.isInteger = function() { var response = true for (var k = this.decPtAfter + 1; (k < this.digitArray.length)&&(response); k++) { if (this.decPtAfter[k] * 1 != 0) { response = false } } return response }
isNegative()
method is determined within the
BigDecimal()
function, and within arithmetic functions as
needed.BigDecimal.prototype.compareTo = function(that) { switch (that.xnsType) { case "Number": return this.compareTo(new BigDecimal(that)) break; case "BigDecimal": var rightSide = that break; case "NaN": return Number.NaN break; /* this < that: -1 this == that: 0 this > that: 1 */ case "Infinity": switch (this.xnsType) { case that.xnsType: return 0 default: return -1 } case "-Infinity": switch (this.xnsType) { case that.xnsType: return 0 default: return 1 } default: var XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].compareTo(XNS_numbers[1]) break; } if ((isXNSNaN(this))||(isXNSNaN(rightSide))) { return Number.NaN // no need to continue } else { var response = 0 // both numbers are valid BigDecimals. } /* this < that: -1 this == that: 0 this > that: 1 */ var isZero = true for (k = 0; (k < this.digitArray.length)&&(isZero); k++) { isZero = (this.digitArray[k] * 1 == 0) } var rightIsZero = true for (k = 0; (k < rightSide.digitArray.length)&&(rightIsZero); k++) { rightIsZero = (rightSide.digitArray[k] * 1 == 0) } if (response != 0) { return response // no need to continue } var isNeg = this.isNegative(), rightIsNeg = rightSide.isNegative() switch (true) { case ((isZero)&&(rightIsZero)): return 0; // 0 == 0 always break; case ((isNeg)&&(!rightIsNeg)): // -3 < 3 case ((isNeg)&&(rightIsZero)): // -3 < 0 case ((!rightIsNeg)&&(isZero)): // 0 < 3 response = -1; break; case ((rightIsNeg)&&(!isNeg)): case ((rightIsNeg)&&(isZero)): case ((!isNeg)&&(rightIsZero)): response = 1; break; case ((this.isNegative()) && (rightSide.isNegative())): var invert = true // -3 > -5; break; } if (response != 0) { return response // no need to continue } switch (true) { case (this.decPtAfter < rightSide.decPtAfter): response = -1 // 499. < 499,000. break; case (this.decPtAfter > rightSide.decPtAfter): response = 1 break; } if (response != 0) { if (invert) { response *= -1 } return response // no need to continue } // Check section by section. var length = Math.min(this.digitArray.length, rightSide.digitArray.length) for (var k = 0; ((k < length)&&(response == 0)); k++) { switch (true) { case (this.digitArray[k] < rightSide.digitArray[k]): response = -1 break; case (this.digitArray[k] > rightSide.digitArray[k]): response = 1 break; } } if (response == 0) { // we still haven't proven an inequality switch (true) { case (this.digitArray.length == rightSide.digitArray.length): break; // same number of digits: the numbers are clearly equal case (this.digitArray.length < rightSide.digitArray.length): var flag = true for (k = this.digitArray.length; (k < rightSide.digitArray.length)&&(flag); k++) { flag = (rightSide.digitArray[k] * 1 == 0) } if (!flag) { response = -1 // 3.14 < 3.14159 } // if the flag == 0, then the extra digits are all zeroes, and the two are equal. break; case (this.digitArray.length > rightSide.digitArray.length): flag = true for (k = rightSide.digitArray.length; (k < this.digitArray.length)&&(flag); k++) { flag = (this.digitArray[k] * 1 == 0) } if (!flag) { response = 1 } break; } } // that should do it if (invert) { response *= -1 } return response // nothing left to check }
BigDecimal.prototype.negate = function() { var response = new BigDecimal(this) if (this.isNegative()) { response.isNegative = returnFalse } else { response.isNegative = returnTrue } return response }
BigDecimal.prototype.add = function(that) { switch (that.xnsType) { case "Number": return this.add(new BigDecimal(that)) // convert to a BigDecimal break; case "BigDecimal": var rightSide = that break; case "NaN": return new XNS_NaN() break; case "Infinity": switch (this.xnsType) { case "NaN": case "-Infinity": return new XNS_NaN() case "BigDecimal": case "Infinity": return new XNS_Infinity() default: var XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].add(XNS_numbers[1]) } case "-Infinity": switch (this.xnsType) { case "NaN": case "Infinity": return new XNS_NaN() case "BigDecimal": case "-Infinity": return new XNS_NEG_Infinity() default: XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].add(XNS_numbers[1]) } default: XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].add(XNS_numbers[1]) } if (arguments.length > 1) { var invert = arguments[1] } else { invert = 1 } if (invert * invert != 1) { throw new Error("Invalid second argument to BigDecimal.prototype.add: " + invert) } // The idea for the invert is to use that in case subtract wants to call on add, or if we have to flip signs. if (this.isNegative()!=that.isNegative()) { invert *= -1 } var response = new BigDecimal(this) // Making sure we have enough zeroes while (response.decPtAfter < rightSide.decPtAfter) { response.digitArray.splice(0,0,0) response.decPtAfter++ } var offset = response.decPtAfter - rightSide.decPtAfter, decimals = rightSide.digitArray.length - rightSide.decPtAfter while (response.digitArray.length - response.decPtAfter < decimals) { response.digitArray[response.digitArray.length] = 0 } // Begin adding sequence for (var k = 0; k < rightSide.digitArray.length; k++) { response.digitArray[k + offset] *= 1 response.digitArray[k + offset] += rightSide.digitArray[k] * invert } response.compactNum() return response }
BigDecimal.prototype.subtract = function(that) { switch (that.xnsType) { case "Number": return this.subtract(new BigDecimal(that)) // convert to a BigDecimal break; case "BigDecimal": var rightSide = that break; case "NaN": return new XNS_NaN() break; case "Infinity": switch (this.xnsType) { case "NaN": case "Infinity": return new XNS_NaN() case "BigDecimal": case "-Infinity": return new XNS_NEG_Infinity() default: var XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].subtract(XNS_numbers[1]) } case "-Infinity": switch (this.xnsType) { case "NaN": case "-Infinity": return new XNS_NaN() case "BigDecimal": case "Infinity": return new XNS_Infinity() default: XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].subtract(XNS_numbers[1]) } default: XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].subtract(XNS_numbers[1]) } return this.add(rightSide, -1) }
BigDecimal.prototype.multiply = function(that) { switch (that.xnsType) { case "Number": return this.multiply(new BigDecimal(that)) // convert to a BigDecimal break; case "BigDecimal": var rightSide = that break; case "NaN": return new XNS_NaN() case "Infinity": var isZero = true for (var k = 0; (k < this.digitArray.length)&&(isZero); k++) { isZero = (this.digitArray[k] * 1 == 0) } if (isZero) { return new XNS_NaN() } if (!this.isNegative()) { return new XNS_Infinity() } return new XNS_NEG_Infinity() case "-Infinity": isZero = true for (k = 0; (k < this.digitArray.length)&&(isZero); k++) { isZero = (this.digitArray[k] * 1 == 0) } if (isZero) { return new XNS_NaN() } if (this.isNegative()) { return new XNS_Infinity() } return new XNS_NEG_Infinity() default: XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].subtract(XNS_numbers[1]) } var response = new BigDecimal(), offset = 0 if (this.isNegative() != rightSide.isNegative()) { response.isNegative = returnTrue } response.decPtAfter = this.decPtAfter + rightSide.decPtAfter while (response.decPtAfter < 0) { response.digitArray.splice(0,0,0) response.decPtAfter++ offset++ } var a = this.digitArray.length var b = rightSide.digitArray.length var c = a + b + offset while (response.digitArray.length < c) { response.digitArray[response.digitArray.length] = 0 } for (a = 0; a < this.digitArray.length; a++) { for (b = 0; b < rightSide.digitArray.length; b++) { response.digitArray[a + b + offset] += this.digitArray[a] * rightSide.digitArray[b] } } response.compactNum() return response }
BigDecimal.prototype.divide = function(that) { switch (that.xnsType) { case "Number": return this.divide(new BigDecimal(that)) // convert to a BigDecimal break; case "BigDecimal": var thatIsZero = true for (var j = 0; (j < that.digitArray.length)&&(thatIsZero); j++) { thatIsZero = (that.digitArray[j] * 1 == 0) } var isZero = true for (var k = 0; (k < this.digitArray.length)&&(isZero); k++) { isZero = (this.digitArray[k] * 1 == 0) } switch (true) { case ((thatIsZero)&&(this.isNegative())): return new XNS_NEG_Infinity() case ((thatIsZero)&&(isZero)): return new XNS_NaN case (thatIsZero): return new XNS_Infinity case (isZero): return new BigDecimal(BigDecimal.ZERO) default: var rightSide = new BigDecimal(that) } break; case "NaN": return new XNS_NaN() case "Infinity": case "-Infinity": return new BigDecimal(BigDecimal.ZERO) default: XNS_numbers = XNS_Convert_Types(this, that) return XNS_numbers[0].subtract(XNS_numbers[1]) } var response = new BigDecimal(), offset = 0 response.decPtAfter = this.decPtAfter - rightSide.decPtAfter while (rightSide.digitArray[0] * 1 == 0) { rightSide.digitArray.shift() offset-- } while ((response.decPtAfter < 0)||(offset < 0)) { response.digitArray.splice(0,0,0) response.decPtAfter++ offset++ } var remainder = new BigDecimal(this) for (var a = 0; a < remainder.digitArray.length; a++) { remainder.digitArray[a] *= 1 } if (remainder.digitArray.length == 1) { remainder.digitArray[1] = 0 } var divisor = ((rightSide.digitArray[0] * BigDecimal.maxSection) + 1) isZero = true for (k = 0; (k < remainder.digitArray.length)&&(isZero); k++) { isZero = (remainder.digitArray[k] * 1 == 0) } for (k = 0; (!isZero)&&(k < BigDecimal.totalSections + 2); k++) { var dividend = remainder.digitArray[0] * BigDecimal.maxSection + remainder.digitArray[1] * 1 var quotient = Math.floor(dividend / divisor) response.digitArray[offset + k] = quotient var subtract = [] for (a = 0; a < rightSide.digitArray.length; a++) { subtract[a] = rightSide.digitArray[a] * quotient } for (a = 0; (a < subtract.length); a++) { if (remainder.digitArray.length == a) { remainder.digitArray[a] = 0 } remainder.digitArray[a] -= subtract[a] } for (a = remainder.digitArray.length - 1; a > 0; a--) { var adjust = Math.floor(remainder.digitArray[a] / BigDecimal.maxSection) remainder.digitArray[a - 1] += Math.floor(remainder.digitArray[a] / BigDecimal.maxSection) remainder.digitArray[a] -= adjust * BigDecimal.maxSection } var carry = remainder.digitArray.shift() remainder.digitArray[0] += carry * BigDecimal.maxSection if (remainder.digitArray.length == 1) { remainder.digitArray[1] = 0 } isZero = true for (a = 0; (a < remainder.digitArray.length)&&(isZero); a++) { isZero = (remainder.digitArray[a] * 1 == 0) } } response.compactNum() if (this.isNegative() != rightSide.isNegative()) { response.isNegative = returnTrue } return response }
BigDecimal.prototype.toString = function() { switch (this.xnsType) { case "NaN": case "Infinity": case "-Infinity": return this.xnsType } var digitArray = this.digitArray.join().split(",") // returns a fresh array digitArray.splice(this.decPtAfter + 1, 0, ".") while (digitArray[0].charAt(0) == "0") { digitArray[0] = digitArray[0].substr(1) } if (digitArray[0].length == 0) { digitArray[0] = 0 } if (digitArray[0] == ".") { digitArray.splice(0,0,0) } if (this.isNegative()) { digitArray.splice(0, 0, "-") } var k = digitArray[digitArray.length - 1] while ((k.charAt(k.length - 1) == "0")&&(this.decPtAfter < this.digitArray.length - 1)) { k = k.substr(0, k.length - 1) } digitArray[digitArray.length - 1] = k if (k == "") { digitArray.length-- } if (digitArray[digitArray.length - 1] == ".") { digitArray.length-- } return digitArray.join("") }
BigDecimal.prototype.toLiteralString = function() { return "new BigDecimal('" + this + "')" }
BigDecimal.prototype.toMathML = Number.prototype.toMathML
BigDecimal.prototype.carryCompact = function() { for (var k = 0; k < this.digitArray.length; k++) { this.digitArray[k] *= 1 } if (this.digitArray[0] < 0) { // ah hah! Negative leftmost section. if (this.isNegative()) { this.isNegative = returnFalse } else { this.isNegative = returnTrue } for (k = 0; k < this.digitArray.length; k++) { this.digitArray[k] *= -1 } } // rolling section adjustments for (k = this.digitArray.length - 1; k > 0; k--) { var adjust = Math.floor(this.digitArray[k] / BigDecimal.maxSection) this.digitArray[k - 1] += Math.floor(this.digitArray[k] / BigDecimal.maxSection) this.digitArray[k] -= adjust * BigDecimal.maxSection } // Leftmost section adjustments if (Math.floor(this.digitArray[0] / BigDecimal.maxSection) > 0) { this.digitArray.splice(0, 0, 0) this.decPtAfter++ k = 1 adjust = Math.floor(this.digitArray[k] / BigDecimal.maxSection) this.digitArray[k - 1] += Math.floor(this.digitArray[k] / BigDecimal.maxSection) this.digitArray[k] -= adjust * BigDecimal.maxSection } for (k = 0; k < this.digitArray.length; k++) { this.digitArray[k] = BigDecimal.addZeroes + this.digitArray[k] this.digitArray[k] = this.digitArray[k].substr(-BigDecimal.sectDigits) } while ((this.digitArray.length > this.decPtAfter)&&(this.digitArray[this.digitArray.length - 1] * 1 == 0)) { this.digitArray.length-- } while (this.digitArray.length < this.decPtAfter + 1) { this.digitArray[this.digitArray.length] = BigDecimal.addZeroes } while ((this.digitArray.length > 0)&&(this.digitArray[0] * 1 == 0)&&(this.decPtAfter > -1)) { this.digitArray.shift() this.decPtAfter-- } if (this.digitArray.length == 0) { this.digitArray.unshift(0) this.decPtAfter = 0 } // check to see if we equal zero var isZero = true for (k = 0; (k < this.digitArray.length)&&(isZero); k++) { isZero = (this.digitArray[k] * 1 == 0) } if (isZero) { this.digitArray = [0] this.isNegative = returnFalse this.decPtAfter = 0 } }
BigDecimal.prototype.compactNum = function() { this.carryCompact() // assume that prior to a rounding section, we may have a carrying operation to act on. /* Rounding section */ var digitsCount = 0 if (this.digitArray[0] * 1 != 0) { digitsCount = BigDecimal.maxDigits - this.digitArray[0].toString().length } else { var k = 0 while ((this.digitArray.length > k)&&(this.digitArray[k] * 1 == 0)) { k++ digitsCount += BigDecimal.sectDigits } digitsCount += BigDecimal.sectDigits if (this.digitArray.length > k) { digitsCount -= (this.digitArray[k] * 1).toString().length } digitsCount += BigDecimal.maxDigits } var index = Math.floor(digitsCount / BigDecimal.sectDigits) - 1 var offset = digitsCount % BigDecimal.sectDigits var altIndex = index, altOffset = offset + 1 if (altOffset == BigDecimal.sectDigits) { altIndex++ altOffset = 0 } if (this.digitArray.length > altIndex) { var roundUp = (this.isNegative() == (this.digitArray[altIndex].toString().charAt(altOffset) * 1 <= 4)) // if this.isNegative() == false and the digit in question is <= 4, the second expression is false, and roundUp == true. if (roundUp) { var digit = this.digitArray[index].toString().charAt(offset) * 1 this.digitArray[index] = this.digitArray[index].toString().substr(0, offset) + (digit + 1) if (digit == 9) { var flag = true } } else { this.digitArray[index] = this.digitArray[index].toString().substr(0, offset + 1) } while (this.digitArray[index].length < BigDecimal.sectDigits) { this.digitArray[index] += "0" } if (flag) { this.digitArray[index] += "0" } if (this.digitArray.length > index + 1) { this.digitArray.length = index + 1 // truncate the digitArray appropriately } } /* Adding zeroes back in section */ var m = 0 while (this.digitArray.length <= this.decPtAfter) { this.digitArray[this.digitArray.length] = BigDecimal.addZeroes } this.carryCompact() // assume that after rounding, we may have a carrying operation to act on. // 0.99999... -> 1.00000... }
Number._toBigDecimal = BigDecimal XNS_Types["BigDecimal"] = true // expected to change in the future to a number value