2012-07-15 17 views
10

że mamy podwójną wartość 12345.6789 (powinien być dynamiczny)Jak wyodrębnić cyfr ułamkowych podwójnego/BigDecimal

Teraz wymóg jest podzielony numer i uzyskać cyfr dziesiętnych i cyfr ułamkowych, które byłyby:

double number = 12345.6789; 
int decimal = 12345; 
int fractional = 6789; 

Otrzymuję część dziesiętną, ale czy mógłbyś wskazać część ułamkową? Wielkie dzięki.

+1

Musisz zdecydować, czy szukasz części ułamkowej reprezentacji * * drukowanej lub jeśli jesteś gotów zaakceptować pozorną różnice w dokładności w rzeczywistej reprezentacji binarnej. – seh

+0

@seh istnieje różnica, że ​​ułamek powinien zawierać tylko cyfry bez przebicia. – Dreamer

+0

Jedynym sposobem jest ustawienie liczby miejsc dziesiętnych do pracy z ... Przykładem z 2 miejscami dziesiętnymi: 0,01 będzie 1, a 0.10 będzie 10. Spójrz na moją odpowiedź. – marcolopes

Odpowiedz

13
double number = 12345.6789; // you have this 
int decimal = (int) number; // you have 12345 
double fractional = number - decimal // you have 0.6789 

Problem polega na tym, że część ułamkowa nie jest zapisywany w pamięci jako „0.6789”, ale może mieć pewne „przesunięcia”, że tak powiem. Na przykład 0.6789 może być przechowywany jako 0.67889999291293929991.

Myślę, że głównym problemem tutaj nie jest coraz część ułamkowa, ale coraz część ułamkową z pewnym precyzją.

Jeśli chcesz uzyskać dokładne wartości przypisane go, może warto rozważyć to (chociaż, że nie jest to czysty roztwór):

String doubleAsText = "12345.6789"; 
double number = Double.parseDouble(doubleAsText); 
int decimal = Integer.parseInt(doubleAsText.split("\.")[0]); 
int fractional = Integer.parseInt(doubleAsText.split("\.")[1]); 

Ale, jak powiedziałem, to jest nie najskuteczniejsze i najczystsze rozwiązanie.

+0

Potrzebuje argumentu String wyrażenia dla metody podziału. Musisz więc użyć "\\". ref: http://stackoverflow.com/a/14833048/2000405 –

5

Nie możesz zrobić dokładnie tego, co chcesz robić.

Jednym z problemów jest numer 1.05 jaki powinien być wynik?

double number = 1.05; 
int decimal = 1; 
int fractional = 5; // Oops! "1.05" and "1.5" give the same result. 

Co powiesz na to?

int fractional = 05; // Still not correct. This is an octal number. 

Innym problemem jest to, że podwójny typ nie może dokładnie reprezentować 12345.6789. Zamiast tego przechowuje nieco inną liczbę. Nazywa się to błędem reprezentacji. Więc część ułamkowa nie będzie faktycznie 6789. Zamiast tego możesz zaokrąglić ją do pewnej liczby miejsc dziesiętnych.

int fractional = (int)Math.round((number - decimal) * 1000); 
+0

Naprawdę nie będzie działać cały czas, ponieważ część ułamkowa może mieć więcej niż 4 cyfry :) – GETah

+0

@ Mark Byers dziękuję za rozwiązanie, ale co z częścią ułamkową jest dynamiczna, więc nie wiemy, jak długo to trwa rozwiązanie * 1000 może nie działać. Jeśli double wynosi 12345.678, to staje się * 100. – Dreamer

+2

@Subarule: Nie dałem ci rozwiązania, dałem ci wyjaśnienie, dlaczego nie można tego zrobić bez zmiany wymagań. Który z wymagań chcesz zmienić? –

2

można przekonwertować do String, znaleźć punkt dziesiętny, uzyskać podciąg a następnie przekształcić z powrotem do Integer.

String numberStr = Double.toString(number); 
String fractionalStr = numberStr.substring(numberStr.indexOf('.')+1); 
int fractional = Integer.valueOf(fractionalStr); 
2

Musisz zdecydować, ile miejsc po przecinku ma wesprzeć. Używam tej metody:

int decimals = 2; 
BigDecimal value = new BigDecimal(123.45).setScale(decimals, RoundingMode.HALF_EVEN); 
BigInteger INTEGER = value.abs().toBigInteger(); 
//(value - INTEGER) * (10^decimais) 
BigInteger DECIMAL = ((value.subtract(new BigDecimal(INTEGER))).multiply(new BigDecimal(10).pow(decimals))).toBigInteger();