Category talk:Wren-big: Difference between revisions

Content added Content deleted
(→‎Source code: Added BigRat and BigRats classes.)
(→‎Source code: Added an option to truncate rather than round to the BigRat.toDecimal method.)
Line 1,510: Line 1,510:
toInt { this.toFloat.truncate }
toInt { this.toFloat.truncate }


// Returns the decimal representation of this BigRat object to 'digits' decimal places accuracy.
// Returns the decimal representation of this BigRat object to 'digits' decimal places.
// If 'rounded' is true, the value is rounded to that number of places with halves
// Halves are rounded away from zero.
// being rounded away from zero. Otherwise the value is truncated to that number of places.
toDecimal(digits) {
toDecimal(digits, rounded) {
if (!(digits is Num && digits.isInteger && digits >= 0)) {
if (!(digits is Num && digits.isInteger && digits >= 0)) {
Fiber.abort("Argument must be a non-negative integer")
Fiber.abort("Argument must be a non-negative integer")
Line 1,520: Line 1,521:
if (this.isNegative && qr[0] == 0) intPart = "-" + intPart
if (this.isNegative && qr[0] == 0) intPart = "-" + intPart
var rem = BigRat.new(qr[1].abs, _d)
var rem = BigRat.new(qr[1].abs, _d)
// need to allow an extra digit for subsequent rounding
// need to allow an extra digit if 'rounding' is true
var shiftedRem = rem * BigRat.new("1e" + (digits+1).toString, BigInt.one)
var digits2 = (rounded) ? digits + 1 : digits
var shiftedRem = rem * BigRat.new("1e" + digits2.toString, BigInt.one)
var decPart = (shiftedRem.num / shiftedRem.den).toString
var decPart = (shiftedRem.num / shiftedRem.den).toString
var finalByte = decPart[-1].bytes[0]
if (rounded) {
var finalByte = decPart[-1].bytes[0]
if (finalByte >= 53) { // last character >= 5
decPart = (BigInt.new(decPart) + 5).toString
if (finalByte >= 53) { // last character >= 5
decPart = (BigInt.new(decPart) + 5).toString
}
decPart = decPart[0...-1] // remove last digit
}
}
decPart = decPart[0...-1] // remove last digit
if (decPart.count < digits) {
if (decPart.count < digits) {
decPart = ("0" * (digits - decPart.count + 1)) + decPart
decPart = ("0" * (digits - decPart.count)) + decPart
}
}
if ((shiftedRem.num % shiftedRem.den) == BigInt.zero) {
if ((shiftedRem.num % shiftedRem.den) == BigInt.zero) {
Line 1,539: Line 1,543:
}
}


// Convenience version of the above which uses a default value of 14 decimal places accuracy.
// Convenience versions of the above which use default values for one or both parameters.
toDecimal { toDecimal(14) }
toDecimal(digits) { toDecimal(digits, true) } // always rounded
toDecimal { toDecimal(14, true) } // 14 digits, always rounded


// Returns a string represenation of this instance in the form "i_n/d" where 'i' is an integer.
// Returns a string represenation of this instance in the form "i_n/d" where 'i' is an integer.