HiveBrain v1.2.0
Get Started
← Back to all entries
patternswiftMinor

Fraction (rational number) structure with custom operators

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
numberwithrationalcustomstructurefractionoperators

Problem

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 + subtracto

Solution

The most of your code looks nice to me, too. Here are some remarks:

  • Your definition of / is wrong. It should use the divisor.



  • Maybe make the creation of Fractions more lightweight by using init(_ numerator: Int, _ denominator: Int) so that you could write Fration(3,4)?



  • By your definition by didSet it is possible to have Fraction(1,0) which might not be intended.



Personally, I would make Fraction an immutable structure. Then you could test for 0 on creation like this

init?(_ numerator: Int, _ denominator: Int) {
    if denominator == 0 { return nil }
    ...
}


and also reduce on creation.

And one more thing, how about this addition?

extension Fraction : IntegerLiteralConvertible {
    init(integerLiteral value: IntegerLiteralType) {
        self.init(numerator:value)
    }
}


With it you can simply write 12 instead of 12.fraction.

Code Snippets

init?(_ numerator: Int, _ denominator: Int) {
    if denominator == 0 { return nil }
    ...
}
extension Fraction : IntegerLiteralConvertible {
    init(integerLiteral value: IntegerLiteralType) {
        self.init(numerator:value)
    }
}

Context

StackExchange Code Review Q#56872, answer score: 5

Revisions (0)

No revisions yet.