Reputation: 71
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
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
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
Reputation: 875
Pretty simple really.
Some((root1,root2))
Check out this article and the rest of the series
Upvotes: 0