user21478621
user21478621

Reputation: 71

How do i return multiple values in Option type in Scala?

def solve(a: Double, b: Double, c: Double): Option[(Double, Double)]= {
val disc = b*b - 4 * a * c;
val root1 = (-b + disc) / 2*a);
val root2 = (-b - disc) / 2*a);
}

I understand that (root1, root2) will create a tuple, and I want to return the tuple in Option type. I wonder how to do it in scala?

Upvotes: 0

Views: 1843

Answers (3)

Yawar
Yawar

Reputation: 11637

The other answers cover parts of what I'm guessing you're trying to do, but not the whole of it, which I think is: implement the quadratic formula returning either a pair of roots or None if there is no solution. Given that, your current implementation is also calculating the formula incorrectly. For reference, the formula is:

x1 = (-b + sqrt(b^2 - 4ac)) / 2a
x2 = (-b - sqrt(b^2 - 4ac)) / 2a

The correct implementation:

def solve(a: Double, b: Double, c: Double): Option[(Double, Double)] = {
  val sqrtDiscriminant = Math.sqrt(b * b - 4 * a * c)
  val twiceA = a * 2

  if (a == 0) None
  else
    Some(
      ((-b + sqrtDiscriminant) / twiceA,
      (-b - sqrtDiscriminant) / twiceA))
}

Upvotes: 2

Eric
Eric

Reputation: 1114

Based on your comment from the answer provided by @WillD, it seems that you want to return None when an exception occurs (presumably in calculating either root1 or root2?) In this case, you could surround each calculation with scala.util.Try, and convert each result to an Option:

import scala.util.Try

def solve(a: Double, b: Double, c: Double): Option[(Double, Double)] = {
  val disc = b*b - 4 * a * c
  val root1: Option[Double] = Try((-b + disc) / (2*a)).toOption
  val root2: Option[Double] = Try((-b - disc) / (2*a)).toOption

  // If both `root1` and `root2` are calculated successfully, return the tupled values.
  for {
    r1 <- root1
    r2 <- root2
  } yield {
    (r1, r2)
  }
}

When we call this method with values 0, 1, and 0, we notice something strange happens:

scala> solve(0,1,0)
res0: Option[(Double, Double)] = Some((NaN,-Infinity))

I'm not entirely sure why, but I believe it has to do with the imprecision of Double. Hopefully someone else can chime in with a better answer as to why this returns NaN and -Infinity. However, if we replace all occurrences of Double with BigDecimal, we get much better precision, as well as the desired output:

import scala.util.Try

def solve(a: BigDecimal, b: BigDecimal, c: BigDecimal): Option[(BigDecimal, BigDecimal)] = {
  val disc = b*b - 4 * a * c
  val root1: Option[BigDecimal] = Try((-b + disc) / (2*a)).toOption
  val root2: Option[BigDecimal] = Try((-b - disc) / (2*a)).toOption

  // If both `root1` and `root2` are calculated successfully, return the tupled values.
  for {
    r1 <- root1
    r2 <- root2
  } yield {
    (r1, r2)
  }
}

scala> solve(0,1,0)
res1: Option[(BigDecimal, BigDecimal)] = None

Upvotes: 0

WillD
WillD

Reputation: 875

Pretty simple really.

Some((root1,root2))

Check out this article and the rest of the series

Upvotes: 0

Related Questions