Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@rampion
Created March 24, 2012 16:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rampion/2185095 to your computer and use it in GitHub Desktop.
Save rampion/2185095 to your computer and use it in GitHub Desktop.
class Rational(n: Int, d: Int) extends Ordered[Rational] {
require( d != 0 )
private val g = Rational.gcd(n.abs, d.abs)
val numer: Int = n/g * d.signum
val denom: Int = d.abs/g
def this(n: Int) = this(n, 1)
override def toString = numer + (if (denom == 1) "" else ("/"+denom))
// default methods
def +(that: Rational): Rational = new Rational( numer * that.denom + that.numer * denom, denom * that.denom )
def -(that: Rational): Rational = this + (-that)
def unary_- = new Rational( -numer, denom )
def abs = new Rational( numer.abs, denom )
def signum = new Rational( numer.signum )
def *(that: Rational): Rational = new Rational( this.numer * that.numer, this.denom * that.denom )
def /(that: Rational): Rational = this * that.inverse
def inverse = new Rational( denom, numer )
def compare(that: Rational) = this.numer * that.denom - that.numer * this.denom
def equals(that: Rational) = this.numer == that.numer && this.denom == that.denom
}
object Rational {
implicit def intToRational(x: Int) = new Rational(x)
private def gcd(a: Int, b: Int) : Int = if (b == 0) a else gcd(b, a % b)
def apply(numer: Int, denom: Int) = new Rational(numer, denom)
def apply(numer: Int) = new Rational(numer)
}
@volodymyrlut
Copy link

volodymyrlut commented Oct 29, 2018

Rationals can be equal not only when their numerator and denominator equals.

def equals(that: Rational) = this.numer.toFloat / this.denom == that.numer.toFloat / that.denom

@crater2150
Copy link

@volodymyrlut in this case, the equal implementation is correct, because the primary constructor always reduces to the smallest possible denominator. Replacing it with a conversion to float OTOH may introduce rounding errors:

// using equals with float
@ Rational(Int.MaxValue - 1, Int.MaxValue).equals(Rational(Int.MaxValue - 2, Int.MaxValue)) 
res1: Boolean = true

@SrTobi
Copy link

SrTobi commented Mar 27, 2020

It's missing a hash method : )

Also should override the equals method like:

override def equals(that: Any) = that match {
  case that: Rational => this.numer == that.numer && this.denom == that.denom
  case _ => false
}

thanks, by the way! Helped me a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment