2014-10-13 30 views
6

Jaki jest najprostszy sposób zmniejszenia wartości Java BigDecimal zawierającej dowolną wartość do postaci kanonicznej, aby dwa numery BigDecimal reprezentujące tę samą liczbę były porównywane równomiernie za pomocą metody equals()?Kanoniczna reprezentacja BigDecimal

ja przetwarzania moich numerów z dowolnych ciągów za pomocą kodu:

BigDecimal x = new BigDecimal(string1, MathContext.DECIMAL64); 
BigDecimal y = new BigDecimal(string2, MathContext.DECIMAL64); 

Od (string1, string2) są dowolne, mogą być, na przykład, ("1", "1.0000") lub ("-32.5", "1981") ...

Co szukam to najprostsza (najkrótsza/najczystszy kod) realizacja metodzie canonicalize dla których powyższe twierdzenie

assert x.compareTo(y) != 0 || 
    (canonicalize(x).equals(canonicalize(y)) && 
    x.compareTo(canonicalize(x)) == 0 && y.compareTo(canonicalize(y)) == 0); 

uda ...:

public static BigDecimal canonicalize(BigDecimal b) { 
    // TODO: 
} 
+5

Po co ci to potrzebne, zamiast po prostu używać 'compareTo'? –

+1

Nie możesz użyć 'x.setScale (y.scale())'? – Keppil

+0

@Keppil, teraz patrzę na dokumenty i wygląda na to, że masz rację: [" Zwraca" BigDecimal ", którego skala jest podaną wartością i której wartość jest liczbowo równa temu' BigDecimal's. "] (http://docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html#setScale-int-) – 0xbe5077ed

Odpowiedz

2

Jeśli chcesz wiedzieć, czy dwa BigDecimal y są równe, niezależnie od skali, wystarczy użyć .compareTo()

public static boolean bigDecimalEquals(BigDecimal b1, BigDecimal b2) { 
    return b1.compareTo(b1) == 0; 
} 

To specjalnie poleca ten in the Javadoc

Dwa obiekty BigDecimal, które mają taką samą wartość, ale mają inną skalę (jak 2,0 i 2,00) są uznawane za równe tą metodą. Ta metoda jest preferowana dla poszczególnych metod dla każdego z sześciu operatorów porównania binarnego (<, ==,>,> =,! =, < =).


Jeśli rzeczywiście chcesz przekonwertować BigDecimal tak że .equals() zadziała, wystarczy użyć metody setScale.

+0

przyjęta do odniesienia do 'setScale()' jak wspomniano przez @ Keppil wcześniej. Z mojego oryginalnego posta powinno być oczywiste, że wiem o 'compareTo()' i nie wymagało tego. – 0xbe5077ed

0

Użyj stripTrailingZeros(). Zwraca to odpowiednik BigDecimal ze zminimalizowaną skalą i jest najprostszym sposobem uzyskania reprezentacji kanonicznej. Jest lepszy niż setScale(), ponieważ pozwala uniknąć problemów z zaokrąglaniem.