Fraction multiplication

Hi, I am starting my Kotlin journey and trying some easy (as easy as Kotlin seems to be) codes for things that come to my mind. I tried to make this code for adding two fractions together. Sorry for making the names so long I still want to keep it detailed for my own comfort of learning.

import kotlin.math.abs

fun main() {
println(“Enter the first fraction (e.g. 1/2):”)
val fraction1 = readLine() ?: “”
println(“Enter the second fraction (e.g. 1/3):”)
val fraction2 = readLine() ?: “”

val result = addFractions(fraction1, fraction2)
println("Sum of fractions: $result")

}

fun addFractions(f1: String, f2: String): String {
val (numerator1, denominator1) = f1.split(“/”).map { it.toInt() }
val (numerator2, denominator2) = f2.split(“/”).map { it.toInt() }

val commonDenominator = denominator1 * denominator2
val newNumerator = numerator1 * denominator2 + numerator2 * denominator1

val gcd = gcd(abs(newNumerator), commonDenominator)
val reducedNumerator = newNumerator / gcd
val reducedDenominator = commonDenominator / gcd

return "$reducedNumerator/$reducedDenominator"

}

fun gcd(a: Int, b: Int): Int {
return if (b == 0) a else gcd(b, a % b)
}

Is there any way or tricks I could make this code shorter? I don’t know if there are some built in libraries that already make this process shorter and easier, and I’d like to find more suggestions.

BigInteger has a gcd function you could use. Either you convert back and forth, or you can do the whole calculation with BigInteger, which is a bit slower, but never overflows. It is almost the same code:

import java.math.BigInteger

fun main() {
    println("Enter the first fraction (e.g. 1/2):")
    val fraction1 = readLine() ?: ""
    println("Enter the second fraction (e.g. 1/3):")
    val fraction2 = readLine() ?: ""

    val result = addFractions(fraction1, fraction2)
    println("Sum of fractions: $result")
}

fun addFractions(f1: String, f2: String): String {
    val (numerator1, denominator1) = f1.split("/").map { it.toBigInteger() }
    val (numerator2, denominator2) = f2.split("/").map { it.toBigInteger() }

    val commonDenominator = denominator1 * denominator2
    val newNumerator = numerator1 * denominator2 + numerator2 * denominator1

    val gcd = newNumerator.gcd(commonDenominator)
    val reducedNumerator = newNumerator / gcd
    val reducedDenominator = commonDenominator / gcd

    return "$reducedNumerator/$reducedDenominator"
}

That said, your code is not really reusable. When you deal with fractions, why not give them their own type, which is independent of the use case (e.g. doesn’t assume that the values are originally Strings)? A modified version could look like this:

import java.math.BigInteger

fun main() {
    println("Enter the first fraction (e.g. 1/2):")
    val fraction1 = readLine() ?: ""
    println("Enter the second fraction (e.g. 1/3):")
    val fraction2 = readLine() ?: ""

    val (numerator1, denominator1) = fraction1.split("/").map { it.toBigInteger() }
    val (numerator2, denominator2) = fraction2.split("/").map { it.toBigInteger() }

    val result = Frac(numerator1, denominator1) + Frac(numerator2, denominator2)
    println("Sum of fractions: $result")

}

data class Frac(val numerator: BigInteger, val denominator: BigInteger) {
    operator fun plus(that: Frac): Frac {
        val commonDenominator = this.denominator * that.denominator
        val newNumerator = this.numerator * that.denominator + that.numerator * this.denominator

        val gcd = newNumerator.gcd(commonDenominator)
        val reducedNumerator = newNumerator / gcd
        val reducedDenominator = commonDenominator / gcd
        return Frac(reducedNumerator, reducedDenominator)
    }
    override fun toString(): String = "$numerator/$denominator"
}

Granted, it is not shorter, but easier to use, and easier to extend.

Of course, serious code would need some checks for the user input, in order to give useful error messages, and not technobabble like “Index out of bounds” or so.

1 Like