2015-01-07 9 views
5

Provare aritmetica in virgola mobile in Groovy. Non hai idea del perché/come/che groovy sta facendo dietro le quinte per provocare questi diversi tipi di comportamenti?Perché Groovy esegue l'aritmetica in virgola mobile in questo modo?

double point2 = 0.2 
double point1 = 0.1 
double point3 = 0.3 

assert point2 + point1 == point3 // false, as expected 
    |  | |  | | 
    0.2 | 0.1 | 0.3 
      |  false 
      0.30000000000000004  

float point2 = 0.2 
float point1 = 0.1 
float point3 = 0.3 

assert point2 + point1 == point3 // false, as expected 
    |  | |  | | 
    0.2 | 0.1 | 0.3 
      |  false 
      0.30000000447034836 

def point2 = 0.2 
def point1 = 0.1 
def point3 = 0.3 

assert point2 + point1 == point3 // this returns true 
assert 0.2 + 0.1 == 0.3 // this returns true 

Ho pensato che avesse a che fare con BigDecimal ma poi ho provato questo.

BigDecimal point2 = 0.2 
BigDecimal point1 = 0.1 
BigDecimal point3 = 0.3 

float point4 = 0.4 

assert point1 + point3 == point4 
    |  | |  | | 
    0.1 | 0.3 | 0.4 
      0.4  false 

Che cosa sta causando questo comportamento?

+0

possibile duplicato di [La matematica in virgola mobile è rotta?] (Http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – tmyklebu

+2

@tmyklebu no questo non è un duplicato di questa domanda; mentre la prima metà indicherebbe che, siccome gli asseriti sono formulati in modo errato, la domanda qui riguarda i cast (impliciti) di tipo groovy per numeri "floaty". – cfrick

+0

@cfrick: capisco. Hai ragione; si tratta del tipo di un letterale a virgola mobile apparente. Per favore perdona il mio dito prurito; Ho visto '0.1' e' 0.2' e '0.3' e ho detto" Oh Dio, non di nuovo ". – tmyklebu

risposta

5

tua def: s ci sono BigDecimals

groovy:000> p1 = 0.1 
===> 0.1 
groovy:000> p1.getClass() 
===> class java.math.BigDecimal 

E equals fallisce per comparsion tra BigDecimal e il galleggiante nativo/doppia

groovy:000> p1.equals(0.1f) 
===> false 
groovy:000> p1.equals(0.1) 
===> true 
groovy:000> p1==0.1f 
===> false 
groovy:000> p1==0.1 
===> true 

Non lo so ancora, perché == lavori per [gg] ouble .

groovy:000> p1.equals(0.1d) 
===> false 
groovy:000> p1==0.1d 
===> true 

La mia ipotesi è, che è sepolto in DefaultTypeTransformation.compareToWithEqualityCheck. Poiché entrambi i lati sono numeri: s.

+0

L'ho capito e ho aggiunto altro alla domanda. – kschmit90

+0

Ok, ma perché equals fallisce per il confronto tra BigDecimal e nativo float/double? Quindi posso confrontare un doppio con un BigDecimal ma non un float? – kschmit90

+3

in realtà penso che tu abbia trovato un bug. La mia ipotesi sarebbe che il BigDecimal è erroneamente convertito in un doppio per il confronto. Ho aperto http://jira.codehaus.org/browse/GROOVY-7238 per tracciare questo – blackdrag

Problemi correlati