2015-01-07 7 views
5

Próbowanie arytmetyki zmiennoprzecinkowej w Groovy. Nie masz pojęcia, dlaczego/jak/co robi groovy za kulisami, aby spowodować te różne typy zachowań?Dlaczego Groovy wykonuje w ten sposób arytmetykę zmiennoprzecinkową?

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 

Myślałem, że ma to związek z BigDecimal, ale potem spróbowałem tego.

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 

Co powoduje takie zachowanie?

+0

możliwy duplikat [Czy matematyka zmiennoprzecinkowa jest zepsuta?] (Http://stackoverflow.com/questions/588004/is-floating-point-math-broken) – tmyklebu

+2

@tmyklebu nie jest to duplikat tego pytania; podczas gdy pierwsza połowa wskazywałaby, że, jak twierdzą stwierdzenia, są błędne, pytanie tutaj dotyczy (niejawnych) typów gromów dla "pływających" liczb. – cfrick

+0

@cfrick: Rozumiem. Masz rację; dotyczy to rodzaju pozornego literału zmiennoprzecinkowego. Proszę wybaczyć mój swędzący palec spustowy; Widziałem "0,1" i "0,2" oraz "0,3" i powiedziałem "O Boże, nie znowu". – tmyklebu

Odpowiedz

5

swój def: y istnieją BigDecimals

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

I equals zawiedzie comparsion między BigDecimal i natywnej pływaka/podwójne

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 

Nie wiesz jeszcze, dlaczego == prace dla [DD] ouble .

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

Zgaduję, że został pochowany w DefaultTypeTransformation.compareToWithEqualityCheck. Ponieważ obie strony są liczbą: s.

+0

Wymyśliłem to i dodałem więcej do pytania. – kschmit90

+0

Okay, ale dlaczego równe wyniki nie udają się dla porównania między BigDecimal i native float/double? Czy mogę porównać double do BigDecimal, ale nie float? – kschmit90

+3

właściwie myślę, że znalazłeś błąd. Moje założenie byłoby takie, że BigDecimal jest błędnie przekonwertowany do podwójnego dla porównania. Otworzyłem http://jira.codehaus.org/browse/GROOVY-7238, aby to śledzić – blackdrag