Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking doubles for equality and Sonar issues

We are checking the quality of our code using Sonar, and Sonar found code which compares a float or double for equality with a constant value like this:

if (x == 0.0) { … }

The value the variable is compared with (0.0) is constant, and in case the variable can be equal to this value, the value also isn't computed but only set via a constant. This is typically used to check whether a variable hasn't been set yet or is still at initialization state, e. g. -1.0 might be used for "not yet set" in cases where the value can only be positive.

So, since these values are never computed but only set from constants, the Sonar complaint is not useful for us. Only for computed values (or fractured ones which are not precisely representable as floats or doubles) a complaint about a test for equality makes sense.

The question I have now is: What is the best practice to change the code so that Sonar does not complain about this anymore?

I see several options:

  1. Extract the "test-for-unset" into a special test function; but that would only reduce the number of occurrences (to 1), not the issue in general.
  2. Mark the code for Sonar to ignore it with a special decorator. But we would like to avoid using such decorators.
  3. Hide the comparison behind sth like (0.0 <= x && x <= 0.0) or !(x != 0.0) (which currently seems to be okay for Sonar).
  4. Calling Double.doubleToRawLongBits() to compare the bits of the values like this: (Double.doubleToRawLongBits(x) != Double.doubleToRawLongBits(0.0)).
  5. Other ideas?

None of these solutions I really like and I thought, maybe, there is a better one out there I can't think of.

like image 246
Alfe Avatar asked Jun 19 '15 15:06

Alfe


People also ask

Why is double not accurate?

doubles are not exact. It is because there are infinite possible real numbers and only finite number of bits to represent these numbers.

Can we compare float and double in Java?

Yes, instead of using equality operator (==), you can use relational operator e.g. less than (<) or greater than (>) to compare float and double values.

How do you compare floating point numbers?

To compare two floating point values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.


2 Answers

I would go with your second option:

Mark the code for Sonar to ignore it with a special decorator.

Don't be a slave to static code analysis tools. They're not perfect, and there's nothing wrong with telling them to shut up. My personal practice when using annotations like @SuppressLint is to include a comment explaining why I'm using it.

That said, I would create a constant so the code is more self-explanatory:

private static final double UNINITIALIZED = 0.0;
if (x == UNINITIALIZED) { … }
like image 126
Kevin Krumwiede Avatar answered Sep 20 '22 01:09

Kevin Krumwiede


The best option here is to mark the issue as false positive and to leave a comment. This way the issue and associated technical debt will disappear from your SonarQube instance, without polluting your code with annotations.

like image 32
Mithfindel Avatar answered Sep 19 '22 01:09

Mithfindel