Test per l’uguaglianza in virgola mobile. (FE_FLOATING_POINT_EQUALITY)

Sto usando un findbug in uno script ANT e non riesco a capire come risolvere due dei miei errori. Ho letto la documentazione, ma non capisco. Ecco i miei errori e il codice che li accompagna:

Errore 1: prova per l’uguaglianza in virgola mobile. (FE_FLOATING_POINT_EQUALITY)

private boolean equals(final Quantity other) { return this.mAmount == convertedAmount(other); } 

Errore 2: EQ_COMPARETO_USE_OBJECT_EQUALS

 public final int compareTo(final Object other) { return this.description().compareTo(((Decision) other).description()); } 

Ho letto la documentazione per il problema ComparesTo che afferma

È fortemente raccomandato, ma non strettamente richiesto (x.compareTo (y) == 0) == (x.equals (y)). In generale, qualsiasi class che implementa l’interfaccia Comparable e viola questa condizione dovrebbe indicare chiaramente questo fatto. La lingua consigliata è “Nota: questa class ha un ordinamento naturale che è incoerente con gli uguali”.

e anche i documenti riguardanti l’uguaglianza in virgola mobile

Questa operazione confronta due valori in virgola mobile per l’uguaglianza. Poiché i calcoli in virgola mobile possono comportare l’arrotondamento, i valori di virgola mobile e doppio potrebbero non essere accurati. Per i valori che devono essere precisi, come i valori monetari, prendere in considerazione l’utilizzo di un tipo a precisione fissa come BigDecimal. Per i valori che non devono essere precisi, prendere in considerazione il confronto per l’uguaglianza all’interno di un intervallo, ad esempio: if (Math.abs (x – y) <.0000001). Vedere la specifica della lingua Java, sezione 4.2.4.

Non capisco però. Qualcuno può aiutare, per favore?

Problema 1:

Per il problema FE_FLOATING_POINT_EQUALITY, non dovresti confrontare due valori float direttamente con l’operatore == , poiché a causa di piccoli errori di arrotondamento, i valori potrebbero essere semanticamente “uguali” per l’applicazione anche se la condizione value1 == value2 non è vera .

Per risolvere questo problema, modifica il tuo codice come segue:

 private boolean equals(final Quantity other) { return (Math.abs(this.mAmount - convertedAmount(other)) < EPSILON); } 

Dove EPSILON è una costante che è necessario definire nel codice e rappresenta piccole differenze accettabili per l'applicazione, ad esempio .0000001.

Problema 2:

Per il problema EQ_COMPARETO_USE_OBJECT_EQUALS: Si consiglia vivamente che, dove x.compareTo(y) restituisce zero, x.equals(y) dovrebbe essere true . Nel tuo codice hai implementato compareTo , ma non hai sovrascritto gli equals , quindi stai ereditando l'implementazione di equals da Object e la condizione sopra non è soddisfatta.

Per risolvere questo problema, x.compareTo(y) override di equals (e forse hashCode ) nella tua class, in modo che quando x.compareTo(y) restituisce 0, x.equals(y) restituirà true .

Per l’avviso di virgola mobile, è necessario ricordare che i float sono un tipo inesatto . Un riferimento standard spesso dato per questo (che vale la pena di leggere una volta forse) è:

Quello che ogni scienziato informatico dovrebbe sapere sull’aritmetica in virgola mobile di David Goldberg.

Poiché i float non sono valori esatti, anche se sembrano uguali quando arrotondati a pochi decimali, possono differire leggermente e non corrispondono.

L’ interfaccia Comparable si aspetta un determinato comportamento dal suo implementatore; l’avvertimento ti sta dicendo che non ti stai aderendo e stai offrendo le azioni suggerite.

Non sono d’accordo con le risposte sopra. Uguali e confrontaPer il confronto in virgola mobile, è sbagliato introdurre gli epsilon.

I valori in virgola mobile possono essere confrontati esattamente da uguali e confrontati, usando semplicemente l’operatore “==”.
Se la tua applicazione usa i float che sono il risultato del calcolo , devi confrontare questi valori con l’approccio epsilon, dovrebbe farlo solo in quel punto in cui è necessario. Ad esempio in un metodo di intersezione della linea matematica.
Ma non in eguali e confronta a.

Questo avvertimento è molto fuorviante. Significa confrontare due float dove a uno è il risultato di un calcolo potrebbe dare un risultato inaspettato. Tuttavia, spesso questi galleggianti, per confrontare, non sono il risultato di un calcolo, come

 static final double INVALID_VALUE = -99.0; if (f == INVALID_VALUE) 

dove f è inizializzato con INVALID_VALUE, in java funzionerà sempre perfettamente. Ma findbugs e sonarcube continueranno a lamentarsi.

Quindi basta aggiungere un filtro ignore a findbugs, in modo da avere due classi MyPoint2D e Myrectangle2D