Reputation: 53806
I'm running a calculation on a group of numbers and some of the results
of those calculations returns result of NaN
or Infinity
After investigating I discovered that the root cause is because of
below arithmetic division :
object doublefun {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val d1 = 0.0 //> d1 : Double = 0.0
val d2 = 0.0 //> d2 : Double = 0.0
val d = d1/d2 //> d : Double = NaN
val i1 = 1.0 //> i1 : Double = 1.0
val i2 = 0.0 //> i2 : Double = 0.0
val i = i1/i2 //> i : Double = Infinity
val o1 = 0 //> o1 : Int = 0
val o2 = 0 //> o2 : Int = 0
val o = o1/o2 //> java.lang.ArithmeticException: / by zero
}
I think asking why NaN
and Infinity
are returned in these cases is more of a
math question but it is interesting that 0/0
throws an ArithmeticException
while 0.0/0.0
does not ?
I'm using the result of these calculation to perform a sort descending : NaN
& Infinity
results in elements appearing first when I require them to appear last.
How can I ensure that for any calculation which returns NaN
or Infinity
that
it appears last when sorted ? Can I check for NaN
or Infinity
within the result of
the calculation and if it satisfies just assign to 0.0
:
if(d == Double.Infinity || d == Double.NaN){
return 0.0
}
Upvotes: 1
Views: 2654
Reputation: 55569
The reason behind the use of NaN
and not an exception is really a more general question, which is explained in this answer.
It's unclear how you're doing your sorting, but by default positive and negative infinity are in the correct sort order, and NaN
comes last (in ascending order):
scala> List(Double.PositiveInfinity, Double.NegativeInfinity, Double.NaN, 0.0, -1.0, 2.0).sorted
res15: List[Double] = List(-Infinity, -1.0, 0.0, 2.0, Infinity, NaN)
Any easy way to modify the behavior would be to map and match a list before sorting.
val list = List(Double.PositiveInfinity, Double.NegativeInfinity, Double.NaN, 0.0, -1.0, 2.0)
list.map {
case d if(d.isNaN) => 0.0 // Or whatever value you'd prefer.
case d if(d.isNegInfinity) => 0.0 // Or whatever value you'd prefer.
case d if(d.isPosInfinity) => 0.0 // Or whatever value you'd prefer.
case d => d
}
In ascending order, Double.NegativeInfinity
comes first, then all of the ascending real numbers, then Double.PositiveInfinity
followed by NaN
. If you want both PositiveInfinity
and NegativeInfinity
as well as NaN
to come last in descending order, then you could map them all to Double.NegativeInfinity
.
Upvotes: 2