Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect a repeating decimal

Tags:

math

ios

swift

I need to detect an infinite quotient. For example, when user divides 1/3, I'm not going to show him 0.333333333333, I'm going show him that result is a repeating decimal.

like image 666
eoLithic Avatar asked Apr 28 '15 16:04

eoLithic


1 Answers

Here is a possible implementation how to compute the decimal expansion of a fraction and detect repeating decimals (i.e. periods in the decimal expansion). It is a translation of the code posted and reviewed in Decimal expansion of a rational number on Code Review to Swift.

The algorithm is just the Long Division, and an array (remainders) is used to check for a periodic decimal expansion. (For the sake of simplicity, it is assumed that the numerator is non-negative and the denominator is positive. This can be generalised if necessary.)

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, e.g. "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}

The periods are simply indicated by curly braces, but it should be easy to modify the code to produce an NSAttributedString which indicates the periods by – for example – horizontal lines.

like image 184
Martin R Avatar answered Oct 20 '22 00:10

Martin R