Category talk:Wren-rat: Difference between revisions

m
→‎Source code: Now uses Wren S/H lexer.
(Added source code for new 'Wren-rat' module.)
 
m (→‎Source code: Now uses Wren S/H lexer.)
 
(14 intermediate revisions by the same user not shown)
Line 1:
===Source code===
<langsyntaxhighlight ecmascriptlang="wren">/* Module "rat.wren" */
 
import "./trait" for Comparable
<lang ecmascript>/* Module "rat.wren" */
 
import "/trait" for Comparable
 
/* Rat represents a rational number as an integral numerator and (non-zero) denominator
Line 9 ⟶ 8:
*/
class Rat is Comparable {
// Maximum safe rational number = 2^53 - 1.
static maxSafe { Rat.fromInt(9007199254740991) }
 
// Private helper function to check that 'o' is a suitable type and throw an error otherwise.
// Numbers and numeric strings are returned as rationals.
Line 17 ⟶ 13:
if (o is Rat) return o
if (o is Num) return Rat.fromFloat(o)
if (o is String) return Rat(o.fromStringcontains("_") && o.contains("/")) ? fromMixedString(o) :
o.contains("/") ? fromRationalString(o) : fromString(o)
Fiber.abort("Argument must either be a rational number, a number or a numeric string.")
}
 
// Private helper functonfunction which returns the greatest common divisor of 'n' and 'd'.
static gcd_(n, d) {
while (d != 0) {
Line 42 ⟶ 39:
 
// Constants.
static zero minusOne { Rat.new( 0-1, 1) }
static onezero { Rat.new( 1 0, 1) }
static twoone { Rat.new( 2 1, 1) }
static tentwo { Rat.new(10 2, 1) }
static halfthree { Rat.new( 1 3, 21) }
static tenthfour { Rat.new( 1 4, 10 1) }
static five { Rat.new( 5, 1) }
static six { Rat.new( 6, 1) }
static seven { Rat.new( 7, 1) }
static eight { Rat.new( 8, 1) }
static nine { Rat.new( 9, 1) }
static ten { Rat.new( 10, 1) }
static half { Rat.new( 1, 2) }
static third { Rat.new( 1, 3) }
static quarter { Rat.new( 1, 4) }
static fifth { Rat.new( 1, 5) }
static sixth { Rat.new( 1, 6) }
static seventh { Rat.new( 1, 7) }
static eighth { Rat.new( 1, 8) }
static ninth { Rat.new( 1, 9) }
static tenth { Rat.new( 1, 10) }
 
// Constructs a new Rat object by passing it a numerator and a denominator.
Line 71 ⟶ 83:
_d = d
}
 
// Convenience method which constructs a new Rat object by passing it just a numerator.
static maxSafenew(n) { Rat.fromIntnew(9007199254740991n, 1) }
 
// Constructs a rational number from an integer.
Line 86 ⟶ 101:
static fromString(s) {
var n
s = s.trim()
if (!(n = Num.fromString(s))) Fiber.abort("Argument must be a numeric string.")
if (n.isInteger) return Rat.new(n, 1)
return fromDecimalString_(s.trim().trimEnd("0"))
}
 
// Constructs a rational number from a string of the form "n/d".
// Improper fractions are allowed.
static fromRationalString(s) {
s = s.trim()
Line 101 ⟶ 118:
return Rat.new(n, d)
}
 
// Constructs a rational number from a string of the form "i_n/d" where 'i' is an integer.
// Improper and negative fractional parts are allowed.
static fromMixedString(s) {
var ind = s.split("_")
if (ind.count != 2) Fiber.abort("Argument is not a suitable string.")
var nd = fromRationalString(ind[1])
var i = Rat.fromString(ind[0])
var neg = i.isNegative || (i.isZero && ind[0][0] == "-")
return neg ? i - nd : i + nd
}
 
// Returns the greater of two rational numbers.
static max(r1, r2) { (r1 < r2) ? r2 : r1 }
 
// Returns the smaller of two rational numbers.
static min(r1, r2) { (r1 < r2) ? r1 : r2 }
 
// Private helper method to compare two integers.
static compareInts_(i, j) { (i - j).sign }
 
// Determines whether a Rat object is always shown as such or, if integral, as an integer.
Line 107 ⟶ 144:
 
// Basic properties.
num { _n } // numerator
den { _d } // denominator
ratio { [_n, _d] } // a two element list of the above
float isInteger { _n/_dtoFloat.isInteger } // convertschecks if tointegral aor Numnot
isIntegerisPositive { float.isInteger_n > 0 } // checks if integral or notpositive
isNegative { _n < 0 } // checks if negative
isUnit { _n.abs == 1 } // checks if plus or minus one
isZero { _n == 0 } // checks if zero
 
// Rounding methods (similar to those in Num class).
ceil { Rat.fromInt(floattoFloat.ceil) } // higher integer
floor { Rat.fromInt(floattoFloat.floor) } // lower integer
truncate { Rat.fromInt(floattoFloat.truncate) } // lower integer, towards zero
round { Rat.fromInt(floattoFloat.round) } // nearer integer
fractionroundUp { this - truncate } >= 0 ? ceil : floor } // fractionalhigher partinteger, (sameaway signfrom as this.num)zero
fraction { this - truncate } // fractional part (same sign as this.num)
 
// Reciprocal
Line 133 ⟶ 174:
-(o) { (o = Rat.check_(o)) && (this + (-o)) }
*(o) { (o = Rat.check_(o)) && Rat.new(_n * o.num, _d * o.den) }
/(o) { (o = Rat.check_(o)) && Rat.new(this_n * o.den, _d * o.inversenum) }
%(o) { (o = Rat.check_(o)) && (this/o - idiv(o) * o) }
 
// Computes integral powers.
pow(i) {
if (!((i is Num) && i.isInteger)) Fiber.abort("Argument must be an integeinteger.r")
if (i == 0) return thisRat.one
varif np(i == _n1) return this.powcopy(i).round
varif dp(i == _d.pow(i-1) return this.roundinverse
var np = _n.pow(i.abs).round
var dp = _d.pow(i.abs).round
return (i > 0) ? Rat.new(np, dp) : Rat.new(dp, np)
}
 
// Returns the square of the current instance.
square { Rat.new(_n * _n , _d *_d) }
 
// Other methods.
inc { this + Rat.one } // increment
dec { this - Rat.one } // decrement
abs { (_n >= 0) ? thiscopy() : -this } // absolute value
sign { _n.sign } // sign
 
// The inherited 'clone' method just returns 'this' as Rat objects are immutable.
Line 156 ⟶ 202:
// Compares this Rat with another one to enable comparison operators via Comparable trait.
compare(other) { (float - other.float).sign }
if ((other is Num) && other.isInfinity) return -other.sign
other = Rat.check_(other)
if (_d == other.den) return Rat.compareInts_(_n, other.num)
return Rat.compareInts_(_n * other.den, other.num * _d)
}
 
// As above but compares the absolute values of the Rats.
compareAbs(other) { this.abs.compare(other.abs) }
 
// Converts the current instance to a Num.
toFloat { _n/_d }
 
// Converts the current instance to an integer with any fractional part truncated.
toInt { this.toFloat.truncate }
 
// Returns a string represenation of this instance in the form "i_n/d" where 'i' is an integer.
toMixedString {
var q = _n / _d
var sign = q < 0 ? "-" : ""
q = q.abs.truncate
var r = _n.abs % _d
return sign + q.toString + "_" + r.toString + "/" + _d.toString
}
 
// Returns the string representation of this Rat object depending on 'showAsInt'.
Line 169 ⟶ 238:
static max(a) { a.reduce { |acc, x| (x > acc) ? x : acc } }
static min(a) { a.reduce { |acc, x| (x < acc) ? x : acc } }
}</syntaxhighlight>
}
 
// Type aliases for classes in case of any name clashes with other modules.
var Rat_Rat = Rat
var Rat_Rats = Rats
var Rat_Comparable = Comparable // in case imported indirectly</lang>
9,482

edits