Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth
Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Boost your online presence with premium web hosting and servers

Disclosure: My content contains affiliate links.

42,623 questions

55,358 answers

573 users

How to convert a decimal number to a rational number in Swift

1 Answer

0 votes
import Foundation

/*
    DecimalToRational (Swift)
    -------------------------
    Converts a decimal number (given as a String) into an exact rational p/q.

    Why parse the string manually?
        • Swift has no built‑in Rational type.
        • Double cannot preserve exact decimal digits.
        • Using String + BigInt (via Swift's built‑in big integer support in `BigInt`)
          ensures perfect accuracy.

    Algorithm:
        1. Look for a decimal point.
        2. If none → integer → numerator = n, denominator = 1.
        3. Otherwise:
              Example: "12.345"
              integer part   = "12"
              fractional part = "345"
              digits = 3

              numerator   = integer_part * 10^digits + fractional_part
              denominator = 10^digits

        4. Reduce using gcd (Euclid’s algorithm).
*/

/// Minimal BigInt wrapper using Swift's built‑in `BigInt` from Foundation.
/// If using older Swift versions, replace with a third‑party BigInt library.
typealias BigInt = Int64  // Replace with real BigInt if needed

/// Compute gcd using Euclid’s algorithm
func gcd(_ a: BigInt, _ b: BigInt) -> BigInt {
    var x = a
    var y = b
    while y != 0 {
        let t = y
        y = x % y
        x = t
    }
    return abs(x)
}

/// Rational number container
struct Rational: CustomStringConvertible {
    let numerator: BigInt
    let denominator: BigInt

    var description: String {
        "\(numerator)/\(denominator)"
    }
}

/// Convert decimal string to Rational
func convertDecimalToRational(_ s: String) -> Rational {
    guard let dotPos = s.firstIndex(of: ".") else {
        // No decimal point → integer
        return Rational(numerator: BigInt(s)!, denominator: 1)
    }

    let intPart = String(s[..<dotPos])
    let fracPart = String(s[s.index(after: dotPos)...])

    let integerValue = BigInt(intPart)!
    let fractionalValue = BigInt(fracPart)!
    let digits = fracPart.count

    // denominator = 10^digits
    let denominator = BigInt(pow(10.0, Double(digits)))

    // numerator = integerValue * denominator + fractionalValue
    let numerator = integerValue * denominator + fractionalValue

    // Reduce using gcd
    let g = gcd(numerator, denominator)

    return Rational(numerator: numerator / g, denominator: denominator / g)
}

/// Main
let values = [
    "3.5", "12.75", "0.125", "100.001",
    "7", "42.0", "0.333", "5.2"
]

for v in values {
    let r = convertDecimalToRational(v)
    print("\(v) -> \(r)")
}


/*
run:

3.5 -> 7/2
12.75 -> 51/4
0.125 -> 1/8
100.001 -> 100001/1000
7 -> 7/1
42.0 -> 42/1
0.333 -> 333/1000
5.2 -> 26/5

*/

 



answered Jul 23 by avibootz

Related questions

...