Created
November 22, 2018 00:30
-
-
Save khaosans/dadd4a3254f5db7478e256a091d66bd9 to your computer and use it in GitHub Desktop.
Rational
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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