import java.math.BigInteger
/*
DecimalToRational (Kotlin)
--------------------------
Converts a decimal number (given as a string) into an exact rational p/q.
Why parse the string manually?
• Kotlin/Java have no built‑in rational type.
• Double cannot preserve exact decimal digits.
• Using strings + BigInteger 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).
*/
data class Rational(val numerator: BigInteger, val denominator: BigInteger) {
override fun toString(): String = "$numerator/$denominator"
}
// Euclid’s GCD algorithm
fun gcd(a: BigInteger, b: BigInteger): BigInteger {
var x = a
var y = b
while (y != BigInteger.ZERO) {
val t = y
y = x % y
x = t
}
return x.abs()
}
// Convert decimal string to Rational
fun convertDecimalToRational(s: String): Rational {
val dotPos: Int = s.indexOf('.')
if (dotPos == -1) {
// No decimal point → integer
return Rational(BigInteger(s), BigInteger.ONE)
}
// Split into integer and fractional parts
val intPart: String = s.substring(0, dotPos)
val fracPart: String = s.substring(dotPos + 1)
val integerValue: BigInteger = BigInteger(intPart)
val fractionalValue: BigInteger = BigInteger(fracPart)
val digits: Int = fracPart.length
// denominator = 10^digits
val denominator: BigInteger = BigInteger.TEN.pow(digits)
// numerator = integerValue * denominator + fractionalValue
val numerator: BigInteger = integerValue * denominator + fractionalValue
// Reduce using gcd
val g: BigInteger = gcd(numerator, denominator)
return Rational(numerator / g, denominator / g)
}
fun main() {
val values: List<String> = listOf(
"3.5", "12.75", "0.125", "100.001",
"7", "42.0", "0.333", "5.2"
)
for (v in values) {
val r: Rational = convertDecimalToRational(v)
println("$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
*/