First, the struct itself:
struct Fraction {
var numerator: Int
var denominator: Int {
didSet (oldDenominator) {
if self.denominator == 0 {
self.denominator = oldDenominator
}
}
}
init() {
self.init(numerator: 0, denominator: 1)
}
init(numerator: Int) {
self.init(numerator: numerator, denominator: 1)
}
init(reciprocalOf denominator: Int) {
self.init(numerator: 1, denominator: denominator)
}
init(numerator: Int, denominator: Int) {
self.numerator = numerator;
self.denominator = denominator;
}
mutating func reduce() {
let gcd = greatestCommonDenominator(self.numerator,self.denominator)
self.numerator /= gcd
self.denominator /= gcd
}
func fraction() -> (numerator:Int,denominator:Int) {
return (self.numerator,self.denominator)
}
}
The GCD function the struct's reduce()
function uses:
func greatestCommonDenominator(first: Int, second: Int) -> Int {
return second == 0 ? first : greatestCommonDenominator(second, first % second)
}
An extension on Int
to conveniently make some of these fractions:
extension Int {
var fraction: Fraction {
return Fraction(numerator: self)
}
var reciprocalOf: Fraction {
return Fraction(reciprocalOf: self)
}
}
And now for the operators. First, your basic add, subtract, multiply, and divide:
@infix func + (first: Fraction, second: Fraction) -> Fraction {
let numerator = (first.numerator * second.denominator) + (first.denominator * second.numerator)
let denominator = (first.denominator * second.denominator)
var frac = Fraction(numerator: numerator, denominator: denominator)
frac.reduce()
return frac
}
@infix func - (first: Fraction, second: Fraction) -> Fraction {
let subtractor = Fraction(numerator: -second.numerator, denominator: second.denominator)
return first + subtractor
}
@infix func * (first: Fraction, second: Fraction) -> Fraction {
let numerator = first.numerator * second.numerator
let denominator = first.denominator * second.denominator
var frac = Fraction(numerator: numerator, denominator: denominator)
frac.reduce()
return frac
}
@infix func / (first: Fraction, second: Fraction) -> Fraction {
let divisor = Fraction(numerator: second.denominator, denominator: second.numerator)
return first * second
}
I don't think the modulo operator makes sense here, given we're dealing with fractions. Is there an operator I'm missing?
Now, the compound assignment operators:
@assignment func += (inout left: Fraction, right: Fraction) {
left = left + right
}
@assignment func -= (inout left: Fraction, right: Fraction) {
left = left - right
}
@assignment func *= (inout left: Fraction, right: Fraction) {
left = left * right
}
@assignment func /= (inout left: Fraction, right: Fraction) {
left = left / right
}
I actually don't know if these are strictly necessary, or if Swift will allow these and assume left = left + right
to be left += right
and overloading is only necessary if you need something custom. I'm not sure.
I also wrote functions for doing math with a fraction and an integer:
@infix func + (fraction: Fraction, integer: Int) -> Fraction {
return fraction + integer.fraction
}
@infix func - (fraction: Fraction, integer: Int) -> Fraction {
return fraction - integer.fraction
}
@infix func * (fraction: Fraction, integer: Int) -> Fraction {
return fraction * integer.fraction
}
@infix func / (fraction: Fraction, integer: Int) -> Fraction {
return fraction / integer.fraction
}
@infix func + (integer: Int, fraction: Fraction) -> Fraction {
return integer.fraction + fraction
}
@infix func - (integer: Int, fraction: Fraction) -> Fraction {
return integer.fraction + fraction
}
@infix func * (integer: Int, fraction: Fraction) -> Fraction {
return integer.fraction * fraction
}
@infix func / (integer: Int, fraction: Fraction) -> Fraction {
return integer.fraction / fraction
}
What can be improved? What's missing?
init
function return an optionalFraction
, with anil
value when the denominator is0
.Fraction(numerator:1, denominator:0)
should NOT just silently return aFraction
object that is invalid and will cause trouble later. Swift's optionals seem tailor-made to handle this situation. \$\endgroup\$