Here's a possible implementation of how to calculate the decimal expansion of a fraction and detect duplicate decimal places (i.e. periods in decimal expansion). This is a translation of the code posted and reviewed in the Decimal Expansion of the Rational Number in Swift's code overview.
An algorithm is a Long Division and an array ( remainders ) is used to check for periodic decimal decomposition. (For simplicity, it is assumed that the numerator is non-negative and the denominator is positive. If necessary, this can be generalized.)
struct DecimalFraction : Printable { let wholePart : Int // Integer part let fractionDigits : [Int] // Fractional digits let repeatingAt : Int? // Position of first repeating digit, or `nil` // Create DecimalFraction from given fraction init(numerator : Int, denominator : Int) { precondition(numerator >= 0, "`numerator` must be non-negative") precondition(denominator > 0, "`denominator` must be positive") wholePart = numerator / denominator var fractionDigits : [Int] = [] var repeatingAt : Int? = nil var rem = (abs(numerator) % denominator) * 10 var remainders : [Int] = [] while (rem > 0 && repeatingAt == nil) { remainders.append(rem) let digit = rem / denominator rem = (rem % denominator) * 10 fractionDigits.append(digit) repeatingAt = find(remainders, rem) } self.fractionDigits = fractionDigits self.repeatingAt = repeatingAt } // Produce a string description, eg "12.3{45}" var description : String { var result = String(wholePart) + "." for (idx, digit) in enumerate(fractionDigits) { if idx == repeatingAt { result += "{" } result += String(digit) } if repeatingAt != nil { result += "}" } return result } }
Examples:
println(DecimalFraction(numerator: 3, denominator: 8)) // 0.375 println(DecimalFraction(numerator: 1, denominator: 3)) // 0.{3} println(DecimalFraction(numerator: 20, denominator: 7)) // 2.{857142} println(DecimalFraction(numerator: 12222, denominator: 990)) // 12.3{45}
Periods are simply indicated by curly braces, but they should easily change the code to create an NSAttributedString that indicates periods, for example, horizontal lines.
source share