You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is an example proposal for a rational number module. A good example use of a rational number
would for when a user wishes to simplify symbolic expressions without needing to worry about
floating point errors. I believe this type would be most useful as an internal currency for symbolic
calculations, where performance is sacrificed for accuracy. This type would also allow for the
division of integers without explicit calculations needing to be performed. Some issues will arise
such as the reduction of fractions to simplest form. Creating a performant algorithm for finding
common factors will be a must. Another important issue will be the conversion of both terminal and
repeating decimal numbers into simplified fractions.
The Rational type would conform to the Real protocol and could be used for both
the real and imaginary components of a Complex value.
Simple Example
structRational{letnumerator:Intletdenominator:Int
// todo - fix this so that infinities are handled properly
vardecimal:Double{
denominator !=0?Double(numerator)/Double(denominator):.infinity
}publicinit(_ numerator:Int, _ denominator:Int){self.numerator = numerator
self.denominator = denominator
}
/// Need to test and refactor this to be more robust.
varisNegative:Bool{if numerator >=0 && denominator >0{returnfalse}elseif numerator <=0 && denominator <0{returnfalse}else{returntrue}}}
// MARK: - Equatable Conformance
extensionRational:Equatable{
// todo: come back and adjust this because using the decimal is a bit of a naive
// approach to checking equivalence.
staticfunc==(lhs:Rational, rhs:Rational)->Bool{return lhs.decimal == rhs.decimal
}}
// MARK: - Comparable Conformance
extensionRational:Comparable{
// todo: Come back and fix for same reason as Equatable.
staticfunc<(lhs:Rational, rhs:Rational)->Bool{return lhs.decimal < rhs.decimal
}}
// MARK: - Int and Rational Math
/// Compute the value of a rational number to the power of an integer.
/// The three main cases are handled
/// * power greater than 0
/// * power less than 0
/// * power equal to 0
/// - important- Relies on a for loop to multiply the numerator and denominator by its self (power-1) times. This could be very slow for large powers.
func pow(base:Rational, power:Int)->Rational{if power ==0{return1}else{varnum= base.numerator
vardenom= base.denominator
for_in1...abs(power)-1{
num *= base.numerator
denom *= base.denominator
}return power >0?RationalNumber(num, denom):RationalNumber(denom, num)}}
// MARK: AdditiveArithmetic Conformance
extensionRational:AdditiveArithmetic{staticvarzero:Rational=0staticfunc+=(lhs:inoutRational, rhs:Rational){
lhs = lhs+rhs
}staticfunc-=(lhs:inoutRational, rhs:Rational){
lhs = lhs-rhs
}}
// MARK: Numeric Conformance
extensionRational:Numeric{varmagnitude:Rational{returnRationalNumber(abs(numerator),abs(denominator))}init?<T>(exactly source:T)where T :BinaryInteger{self.numerator =Int(source)self.denominator =1}staticfunc*=(lhs:inoutRational, rhs:Rational){
lhs = lhs*rhs
}}
// MARK: - (Rational, Rational) Math
extensionRational{staticfunc*(lhs:Rational, rhs:Rational)->Rational{returnRational(lhs.numerator*rhs.numerator,
lhs.denominator*rhs.denominator)}staticfunc/(lhs:Rational, rhs:Rational)->Rational{returnRational(lhs.numerator*rhs.denominator,
lhs.denominator*rhs.numerator)}staticfunc+(lhs:Rational, rhs:Rational)->Rational{returnRational(lhs.numerator*rhs.denominator + lhs.denominator*rhs.numerator,
lhs.denominator*rhs.denominator)}staticfunc-(lhs:Rational, rhs:Rational)->Rational{returnRational(lhs.numerator*rhs.denominator - lhs.denominator*rhs.numerator,
lhs.denominator*rhs.denominator)}staticfunc ^(lhs:Rational, rhs:Int)->Rational{returnpow(base: lhs, power: rhs)}staticprefixfunc-(input:Rational)->Rational{returnRational(-input.numerator, input.denominator)}}
// MARK: - ExpressibleByIntegerLiteral Conformance
extensionRational:ExpressibleByIntegerLiteral{init(integerLiteral value:Int){
numerator = value
denominator =1}}
// MARK: - Sequence Extension
extensionSequencewhere Element:Numeric{func product()->Element{returnreduce(1,*)}}
Can you give some examples of the use cases you have in mind for this module? Broadly speaking, my experience is that fixed-width rational numbers (i.e rational numbers that use a fixed-size integer type for the numerator and denominator) are not very useful, because most non-trivial computations will overflow the denominator after a few operations, and computations that don't suffer from that problem involve numbers that all share a common unit scaling, so scaled-integer or floating-point would always be a better option.
I'm not opposed to adding a rational type, but to get this started I'd like to see less implementation and more justification.
Thank you so much for your response @stephentyrone. I see what you mean about the use cases and limitations. I will write up a a list of use cases with their justifications and limitations(I may need some help noticing them).
Rational Number Data Type
This is an example proposal for a rational number module. A good example use of a rational number
would for when a user wishes to simplify symbolic expressions without needing to worry about
floating point errors. I believe this type would be most useful as an internal currency for symbolic
calculations, where performance is sacrificed for accuracy. This type would also allow for the
division of integers without explicit calculations needing to be performed. Some issues will arise
such as the reduction of fractions to simplest form. Creating a performant algorithm for finding
common factors will be a must. Another important issue will be the conversion of both terminal and
repeating decimal numbers into simplified fractions.
The
Rational
type would conform to theReal
protocol and could be used for boththe real and imaginary components of a
Complex
value.Simple Example
Tests
The text was updated successfully, but these errors were encountered: