Skip to content

Instantly share code, notes, and snippets.

@khaosans
Created November 22, 2018 00:30
Show Gist options
  • Save khaosans/dadd4a3254f5db7478e256a091d66bd9 to your computer and use it in GitHub Desktop.
Save khaosans/dadd4a3254f5db7478e256a091d66bd9 to your computer and use it in GitHub Desktop.
Rational
package rationals
import java.math.BigInteger
val ZERO = Rational(0.toBigInteger(), 1.toBigInteger())
fun main(args: Array<String>) {
-(1 divBy 2)
(-1 divBy 2)
val r1 = 1 divBy 2
val r2 = 2000000000L divBy 4000000000L
val rational = "1/2".toRational() - "1/3".toRational()
println(rational)
println(r1 == r2)
println((2 divBy 1).toString() == "2")
println((-2 divBy 4).toString() == "-1/2")
println("117/1098".toRational().toString() == "13/122")
println("1/2".toRational() - "1/3".toRational() == "1/6".toRational())
println("1/2".toRational() + "1/3".toRational() == "5/6".toRational())
println(-(1 divBy 2) == (-1 divBy 2))
println((1 divBy 2) * (1 divBy 3) == "1/6".toRational())
println((1 divBy 2) / (1 divBy 4) == "2".toRational())
println((1 divBy 2) < (2 divBy 3))
println((1 divBy 2) in (1 divBy 3)..(2 divBy 3))
println("912016490186296920119201192141970416029".toBigInteger() divBy
"1824032980372593840238402384283940832058".toBigInteger() == 1 divBy 2)
}
infix fun Int.divBy(that: Int): Rational {
return Rational(this.toBigInteger(), that.toBigInteger())
}
infix fun BigInteger.divBy(that: BigInteger): Any {
return Rational(this, that)
}
operator fun Rational.compareTo(that: Rational): Int {
val lhs = this.num * that.den
val rhs = this.den * that.num
if (lhs < rhs) return -1
return if (lhs > rhs) +1 else 0
}
operator fun Rational.div(that: Rational): Rational {
return this.times(Rational(that.den, that.num))
}
operator fun Rational.times(that: Rational): Rational {
// reduce p1/q2 and p2/q1, then multiply, where a = p1/q1 and b = p2/q2
val c = Rational(this.num, that.den)
val d = Rational(that.num, this.den)
return Rational(c.num * d.num, c.den * d.den)
}
operator fun Rational.unaryMinus(): Rational {
return Rational(-this.num, this.den)
}
fun String.toRational(): Rational {
val split = this.split("/")
return if (split.size > 1) {
Rational(split[0].toBigInteger(), split[1].toBigInteger())
} else {
Rational(split[0].toBigInteger(), 1.toBigInteger())
}
}
infix fun Long.divBy(that: Long): Rational {
return Rational(this.toBigInteger(), that.toBigInteger())
}
class Rational(_n: BigInteger, _d: BigInteger) : Comparable<Rational> {
var num: BigInteger = 0.toBigInteger() // the numerator
var den: BigInteger = 0.toBigInteger() // the denominator
// create and initialize a new Rational object
init {
if (_d == 0.toBigInteger()) {
throw ArithmeticException("denominator is zero")
}
// reduce fraction
val g = gcd(_n, _d)
num = _n / g
den = _d / g
// needed only for negative numbers
if (den < 0.toBigInteger()) {
den = -den
num = -num
}
}
override fun compareTo(that: Rational): Int {
val lhs = this.num * that.den
val rhs = this.den * that.num
if (lhs < rhs) return -1
return if (lhs > rhs) +1 else 0
}
fun gcd(n1: BigInteger, n2: BigInteger): BigInteger {
return if (n2 != 0.toBigInteger())
gcd(n2, n1 % n2)
else
n1
}
operator fun minus(that: Rational): Rational {
return this.plus(Rational((-that.num), (that.den)))
}
operator fun plus(that: Rational): Rational {
// special cases
if (this.compareTo(ZERO) == 0) return that
if (that.compareTo(ZERO) === 0) {
return this
}
val f = gcd(this.num, that.num)
val g = gcd(this.den, that.den)
// add cross-product terms for numerator
val s = Rational(this.num / f * (that.den / g) + that.num / f * (this.den / g),
this.den * (that.den / g))
// multiply back in
s.num *= f
return s
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Rational
return this.compareTo(other) == 0
}
override fun hashCode(): Int {
var result = num.hashCode()
result = 31 * result + den.hashCode()
return result
}
override fun toString(): String {
return if (den == 1.toBigInteger()) {
num.toString()
} else {
num.toString() + "/" + den.toString()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment