rspec/rules/S1244/java/rule.adoc
Fred Tingaud 16f6c0aecf
Inline adoc when include has no additional value (#1940)
Inline adoc files when they are included exactly once.

Also fix language tags because this inlining gives us better information
on what language the code is written in.
2023-05-25 14:18:12 +02:00

109 lines
4.1 KiB
Plaintext

== Why is this an issue?
Floating point math is imprecise because of the challenges of storing such values in a binary representation. Even worse, floating point math is not associative; push a ``++float++`` or a ``++double++`` through a series of simple mathematical operations and the answer will be different based on the order of those operation because of the rounding that takes place at each step.
Even simple floating point assignments are not simple:
----
float f = 0.1; // 0.100000001490116119384765625
double d = 0.1; // 0.1000000000000000055511151231257827021181583404541015625
----
(Results will vary based on compiler and compiler settings);
Therefore, the use of the equality (``++==++``) and inequality (``++!=++``) operators on ``++float++`` or ``++double++`` values is almost always an error. Instead the best course is to avoid floating point comparisons altogether. When that is not possible, you should consider using one of Java's float-handling ``++Numbers++`` such as ``++BigDecimal++`` which can properly handle floating point comparisons. A third option is to look not for equality but for whether the value is close enough. I.e. compare the absolute value of the difference between the stored value and the expected value against a margin of acceptable error. Note that this does not cover all cases (``++NaN++`` and ``++Infinity++`` for instance).
This rule checks for the use of direct and indirect equality/inequailty tests on floats and doubles.
=== Noncompliant code example
[source,java]
----
float myNumber = 3.146;
if ( myNumber == 3.146f ) { //Noncompliant. Because of floating point imprecision, this will be false
// ...
}
if ( myNumber != 3.146f ) { //Noncompliant. Because of floating point imprecision, this will be true
// ...
}
if (myNumber < 4 || myNumber > 4) { // Noncompliant; indirect inequality test
// ...
}
float zeroFloat = 0.0f;
if (zeroFloat == 0) { // Noncompliant. Computations may end up with a value close but not equal to zero.
}
----
=== Exceptions
Since ``++NaN++`` is not equal to itself, the specific case of testing a floating point value against itself is a valid test for ``++NaN++`` and is therefore ignored. Though using ``++Double.isNaN++`` method should be preferred instead, as intent is more explicit.
[source,java]
----
float f;
double d;
if(f != f) { // Compliant; test for NaN value
System.out.println("f is NaN");
} else if (f != d) { // Noncompliant
// ...
}
----
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
=== Message
Equality tests should not be made with floating point values.
'''
== Comments And Links
(visible only on this page)
=== on 2 Oct 2014, 09:01:20 Nicolas Peru wrote:
Updated message and description based on : \http://www.ibm.com/developerworks/library/j-jtp0114/#N101EA
Please review.
The trick here is to report a correct error message.
I am not sure we should detect indirect equality detection as stated in main description (see previous link).
I am also wondering about a recommandation to use BigDecimal.compareTo instead of a float equality.
I think we should definitely detect those float (in)equality but I am really wondering about what we should recommend as a fix for this issue.
=== on 3 Oct 2014, 18:51:33 Ann Campbell wrote:
\[~nicolas.peru] for buggy code code don't always have to suggest a fix since there can be many ways to handle it.
Having finally read some of the reference you provided, I've updated the description to offer 3 courses of action
* just don't do it
* just a Number such as BigDecimal
* compare vs margin of error
Also, I had inadvertently deleted the wrong code sample. Noncompliant code restored to last state (still missing indirect equality tests) and Compliant solution removed.
=== on 9 Oct 2014, 08:59:51 Nicolas Peru wrote:
\[~ann.campbell.2] After mail discussion I updated description, feel free to correct it.
=== on 9 Oct 2014, 11:49:16 Ann Campbell wrote:
\[~nicolas.peru] I've updated the inline comments (and code formatting)
include::../comments-and-links.adoc[]
endif::env-github,rspecator-view[]