Category talk:Wren-big: Difference between revisions
Content added Content deleted
(→Source code: Rewrote BigDec.toFloat method which was buggy previously.) |
(→Source code: Added some new methods to BigDec class including exp and log.) |
||
Line 2,135: | Line 2,135: | ||
static phi { new("1.6180339887498948482045868343656381177203091798057628621354486227", 64) } |
static phi { new("1.6180339887498948482045868343656381177203091798057628621354486227", 64) } |
||
static sqrt2 { new("1.4142135623730950488016887242096980785696718753769480731766797380", 64) } |
static sqrt2 { new("1.4142135623730950488016887242096980785696718753769480731766797380", 64) } |
||
// Returns 'pi' to a given precision using the Almqvest Berndt AGM method. |
|||
// See https://rosettacode.org/wiki/Arithmetic-geometric_mean/Calculate_Pi for details. |
|||
static pi(prec) { |
|||
if (prec < 16) prec = 16 |
|||
var an = BigRat.one |
|||
var bn = BigRat.half.sqrt(prec) |
|||
var tn = BigRat.half.square |
|||
var pn = BigRat.one |
|||
while (pn <= prec) { |
|||
var prevAn = an |
|||
an = (bn + an) * BigRat.half |
|||
bn = (bn * prevAn).sqrt(prec) |
|||
prevAn = prevAn - an |
|||
tn = tn - (prevAn.square * pn) |
|||
pn = pn + pn |
|||
} |
|||
var res = (an + bn).square / (tn * 4) |
|||
return BigDec.fromBigRat(res, prec) |
|||
⚫ | |||
// Returns the greater of two BigDec objects. |
// Returns the greater of two BigDec objects. |
||
Line 2,250: | Line 2,270: | ||
copy() { BigDec.new_(_br.copy(), _prec) } |
copy() { BigDec.new_(_br.copy(), _prec) } |
||
// Compares this BigDec with 'other' to enable comparison operators via Comparable trait. |
|||
compare(other) { (other is BigDec) ? _br.compare(other.br_) : _br.compare(other) } |
compare(other) { (other is BigDec) ? _br.compare(other.br_) : _br.compare(other) } |
||
// As above but compares absolute values. |
// As above but compares absolute values. |
||
compareAbs(other) { (other is BigDec) ? _br.compareAbs(other.br_) : _br.compareAbs(other) } |
compareAbs(other) { (other is BigDec) ? _br.compareAbs(other.br_) : _br.compareAbs(other) } |
||
⚫ | |||
// Returns this BigDec expressed as a BigInt with any fractional part truncated. |
// Returns this BigDec expressed as a BigInt with any fractional part truncated. |
||
toBigInt { _br.num/_br.den } |
toBigInt { _br.num/_br.den } |
||
Line 2,282: | Line 2,302: | ||
toString { toString(_prec, true, false) } // precision digits, always rounded |
toString { toString(_prec, true, false) } // precision digits, always rounded |
||
toDefaultString { toString(16, true, false) } // 16 digits, always rounded |
toDefaultString { toString(16, true, false) } // 16 digits, always rounded |
||
// Private worker method for exponentiation using Taylor series. |
|||
exp_ { |
|||
var y = _br |
|||
var x = _br |
|||
var z = _br |
|||
var res = x + BigRat.one |
|||
var eps = BigRat.new(BigInt.one, BigInt.ten.pow(_prec)) |
|||
var k = 2 |
|||
var fact = BigRat.two |
|||
while (x.abs > eps) { |
|||
z = z * y |
|||
x = z / fact |
|||
res = res + x.round(_prec+2) |
|||
k = k + 1 |
|||
fact = fact * k |
|||
} |
|||
return BigDec.fromBigRat(res, _prec) |
|||
} |
|||
// Returns the exponential of this instance (e ^ this) to the same precision. |
|||
exp { |
|||
if (_br.isInteger) return exp_ |
|||
return (truncate/2).exp_.square * fraction.exp_ |
|||
} |
|||
// Private worker method for natural logarithm using Taylor series. |
|||
log_ { |
|||
var y = _br |
|||
var x = (y - BigRat.one) / (y + BigRat.one) |
|||
var z = x * x |
|||
var res = BigRat.zero |
|||
var eps = BigRat.new(BigInt.one, BigInt.ten.pow(_prec)) |
|||
var k = 1 |
|||
while (x.abs > eps) { |
|||
res = res + (BigRat.two * x / k).round(_prec+2) |
|||
x = (x * z).round(_prec+2) |
|||
k = k + 2 |
|||
} |
|||
return BigDec.new_(res, _prec) |
|||
} |
|||
// Returns the natural logarithm of this instance to the same precision. |
|||
log { |
|||
if (sign <= 0) Fiber.abort("Instance must be positive.") |
|||
if (this < BigDec.two) return log_ |
|||
var d = this.copy() |
|||
var pow = 0 |
|||
var two = BigDec.new(2, _prec) |
|||
while (d >= two) { |
|||
d = d / 2 |
|||
pow = pow + 1 |
|||
} |
|||
return d.log_ + two.log_ * pow |
|||
} |
|||
// Returns this ^ f where f may be fractional. |
|||
powf(f) { |
|||
if ((f is Num) && f.isInteger) return pow(f) |
|||
return (log * f).exp |
|||
} |
|||
} |
} |
||