import scala.math.BigInt
/*
DecimalToRational (Scala)
-------------------------
Converts a decimal number (given as a string) into an exact rational p/q.
Why parse the string manually?
• Scala has no built‑in rational type.
• Double cannot preserve exact decimal digits.
• Using strings + 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).
*/
case class Rational(numerator: BigInt, denominator: BigInt) {
override def toString: String = s"$numerator/$denominator"
}
object DecimalToRational {
// Euclid’s GCD algorithm
def gcd(a: BigInt, b: BigInt): BigInt = {
if (b == 0) a.abs else gcd(b, a % b)
}
// Convert decimal string to Rational
def convertDecimalToRational(s: String): Rational = {
val dotPos = s.indexOf('.')
if (dotPos == -1) {
// No decimal point → integer
Rational(BigInt(s), BigInt(1))
} else {
val intPart = s.substring(0, dotPos)
val fracPart = s.substring(dotPos + 1)
val integerValue = BigInt(intPart)
val fractionalValue = BigInt(fracPart)
val digits = fracPart.length
// denominator = 10^digits
val denominator = BigInt(10).pow(digits)
// numerator = integerValue * denominator + fractionalValue
val numerator = integerValue * denominator + fractionalValue
// Reduce fraction
val g = gcd(numerator, denominator)
Rational(numerator / g, denominator / g)
}
}
def main(args: Array[String]): Unit = {
val values = Seq(
"3.5", "12.75", "0.125", "100.001",
"7", "42.0", "0.333", "5.2"
)
values.foreach { v =>
val r = convertDecimalToRational(v)
println(s"$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
*/