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:
(0.0 <= x && x <= 0.0)
or !(x != 0.0)
(which currently seems to be okay for Sonar).Double.doubleToRawLongBits()
to compare the bits of the values like this: (Double.doubleToRawLongBits(x) != Double.doubleToRawLongBits(0.0))
.None of these solutions I really like and I thought, maybe, there is a better one out there I can't think of.
doubles are not exact. It is because there are infinite possible real numbers and only finite number of bits to represent these numbers.
Yes, instead of using equality operator (==), you can use relational operator e.g. less than (<) or greater than (>) to compare float and double values.
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.
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) { … }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With