Jak uzyskać pełne i ułamkowe części z double w JSP / Java?


104

Jak uzyskać pełne i ułamkowe części z double w JSP / Java? Jeśli wartość wynosi 3,25, to chcę uzyskać fractional =.25,whole = 3

Jak możemy to zrobić w Javie?


4
Wydaje się, że masz niedokładne pojęcie o tym, czym są mantysa i wykładnik. Nie są tylko „całą częścią” i „częścią ułamkową”. Zobacz en.wikipedia.org/wiki/Floating_point
Jon Skeet,

Właściwie przeczytałem około 5 postów, zanim zacząłem „hej… to nie jest nazywane wykładnikiem”. Mój mózg wyrzucił słowa i zaczął rozwiązywać problem .. złe nawyki, które dały mi czytanie rzeczy z programowania :)
Gishu

1
Proszę również przeformułować pytanie OP .. między innymi dla potomności.
Gishu,

1
Brzmi podejrzanie jak problem z pracą domową.
Brian Knoblauch,

Ohh widzę. już się zastanawiałem, jak on osiąga tak dziwne wyniki
Johannes Schaub - litb

Odpowiedzi:


102

http://www.java2s.com/Code/Java/Data-Type/Obtainingtheintegerandfractionalparts.htm

double num;
long iPart;
double fPart;

// Get user input
num = 2.3d;
iPart = (long) num;
fPart = num - iPart;
System.out.println("Integer part = " + iPart);
System.out.println("Fractional part = " + fPart);

Wyjścia:

Integer part = 2
Fractional part = 0.2999999999999998

61
Właściwie ta strona jest pierwszym trafieniem w wyszukiwarce Google dla „uzyskać ułamkową i całą część z podwójnego java” =)
Chris

12
W rzeczywistości ta odpowiedź jest nieprawidłowa, ponieważ wartości większe niż długie mogą reprezentować, dadzą ogromne liczby w części ułamkowej. Odpowiedź Dana Vintona poniżej jest równie prosta i zawsze zwraca poprawny wynik.
arberg

2
więc w rzeczywistości nie jest to poprawne, jak widać na wyjściu. dane wejściowe to ułamek 3, a wyjście to 29999999 ... użycie BigDecimal zamiast Double załatwi sprawę
Alex

2
@Alex Nie, dane wejściowe to liczba bardzo bliska 2.3, ale na pewno nie 2.3. Nie ma nic złego w wynikach, chyba że potrzebujesz więcej niż 10 poprawnych cyfr. Wszystko, czego potrzebujesz, to zaokrąglenie każdego wyniku (np. Formatu %.9f), co zwykle jest mniej bolesne niż BigDecimal. Jedyny problem to przepełnienie.
maaartinus

1
Zamiana double na int jest prawie zawsze złym pomysłem. Ponieważ np. Dla (long)1.0e100ciebie dostaniesz 0. Często potrzebujesz podwójnej wartości po prostu „floored”, dla której jest floor(). Jeśli chcesz używać zarówno części całkowych, jak i ułamkowych, użyj modf(). Naprawdę, to zła odpowiedź.
mojuba

155
double value = 3.25;
double fractionalPart = value % 1;
double integralPart = value - fractionalPart;

12
Dlaczego jest to odrzucane? Działa dobrze, a moja edycja będzie działać również z wartościami ujemnymi.
HRJ

Część całkowita może mieć postać => long longPart = (long) 3.25
jdurango

2
Nie będzie działać dla Neg. wartości. To znaczy -3,25% 1 = 0,75 a nie 0,25. Tak więc integralnaPart będzie wynosić -3,25 - 0,75 = -4.
WindRider,

2
@WindRider, sprawdziłem, czy nie ma wartości ujemnych ... i jak działa ... jednak dla miejsc po przecinku, których jest mała liczba, wystąpi niewielki błąd. Dawny. dla -03.0025 zwraca -0,00249999999999467 i -3,0
justshams

5
Zamieszanie polega na tym, że niektóre języki, takie jak Python, używają %określenia modulo ( -3.25 % 1 == 0.75), a inne, takie jak Java, Fortran, C i C ++, %oznaczają resztę ( -3.25 % 1 == -0.25). WindRider mógł wpisać go w Python REPL ze względów praktycznych, ale ta odpowiedź jest myląca, ponieważ to pytanie dotyczy JVM.
Jim Pivarski

24

Ponieważ to jednoroczne pytanie zostało uruchomione przez kogoś, kto poprawił temat pytania, a to pytanie zostało oznaczone tagiem jspi nikt tutaj nie był w stanie udzielić odpowiedzi ukierunkowanej na JSP, oto mój wkład ukierunkowany na JSP.

Zastosowanie JSTL (tylko kropla JSTL-1.2.jar w /WEB-INF/lib) FMT TagLib. Jest <fmt:formatNumber>tag, który robi dokładnie to, co chcesz iw dość łatwy sposób z pomocą atrybutów maxFractionDigitsi maxIntegerDigits.

Oto SSCCE , po prostu skopiuj i wklej i uruchom.

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%
    // Just for quick prototyping. Don't do this in real! Use servlet/javabean.
    double d = 3.25;
    request.setAttribute("d", d);
%>

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 343584</title>
    </head>
    <body>
        <p>Whole: <fmt:formatNumber value="${d}" maxFractionDigits="0" />
        <p>Fraction: <fmt:formatNumber value="${d}" maxIntegerDigits="0" />
    </body>
</html>

Wynik:

Całość: 3

Frakcja: 0,25

Otóż ​​to. Nie trzeba go masować za pomocą surowego kodu Java.


8

Pierwotne pytanie dotyczyło wykładnika i mantysy, a nie części ułamkowej i całej.

Aby uzyskać wykładnik i mantysę z podwójnej postaci, możesz przekonwertować ją na reprezentację IEEE 754 i wyodrębnić bity w następujący sposób:

long bits = Double.doubleToLongBits(3.25);

boolean isNegative = (bits & 0x8000000000000000L) != 0; 
long exponent      = (bits & 0x7ff0000000000000L) >> 52;
long mantissa      =  bits & 0x000fffffffffffffL;

Nie jest pierwszym bitem mantinssa domyślnie ustawionym na 1, więc mantysa powinna być (bity & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus to nie było wyjście rytmu Wyjście: wykładnik 0 i mantysa 2814749767106560 i jeśli wybierzesz urs agnul, mantysa to 0
Vinayak Bevinakatti

Zerwany z 4 pozytywnymi głosami :) Chociaż widzę, co kod próbuje zrobić, rozbijając podwójną wartość na swoich połączeniach, kod nie wydaje się wyświetlać poprawnych wartości.
Gishu,

@agnul: Myślę, że „mantysa” zwykle odnosi się tylko do wartości bitów. Możesz po prostu przekonwertować to na istotę, dodając (czasami) 1 bit na początku. Jednak według Wikipedii słowo mantysa jest obecnie zastępowane terminem „ułamek”.
Rasmus Faber,

5

Główna logika: musisz najpierw ustalić, ile cyfr znajduje się po przecinku.
Ten kod działa dla dowolnej liczby do 16 cyfr. Jeśli używasz BigDecimal, możesz uruchomić go tylko dla maksymalnie 18 cyfr. wstaw wartość wejściową (swój numer) do zmiennej "num", tutaj jako przykład zakodowałem go na stałe.

double num, temp=0;
double frac,j=1;

num=1034.235;
// FOR THE FRACTION PART
do{
j=j*10;
temp= num*j;
}while((temp%10)!=0);       

j=j/10;
temp=(int)num;
frac=(num*j)-(temp*j);

System.out.println("Double number= "+num);      
System.out.println("Whole part= "+(int)num+" fraction part= "+(int)frac);

Stary, to niezwykle skomplikowana odpowiedź na prosty problem. Czy spojrzałeś na zaakceptowaną odpowiedź?
Gray

1
Teraz osoba, która głosowała „przeciw” (przy okazji nie ja), powinna była wyjaśnić, dlaczego głosowanie „przeciw” nastąpiło. To nie jest dobrze. Ale każdy z nas miał w pewnym momencie 1 punkt.
Gray

2
@Gray pytanie polegało na oddzieleniu 3,25 jako „3” i „25”, a zaakceptowana odpowiedź nigdy, przenigdy nie da „25”, zawsze da „2599999999”
OnePunchMan

@Gray Wiem, kto to przegłosował, to był facet o imieniu Eji (stary użytkownik), który kpił z każdego mojego komentarza, odpowiedzi i pytań, które publikuję na tym blogu. Na koniec piszę do moderatora.
OnePunchMan

2
Ta odpowiedź jest bardzo przydatna, jeśli chcesz, aby część ułamkowa była liczbą całkowitą
Guilherme Campos Hazan

5

Mantysa i wykładnik podwójnej liczby zmiennoprzecinkowej IEEE to takie wartości

value = sign * (1 + mantissa) * pow(2, exponent)

jeśli mantysa ma postać 0,101010101_base 2 (tj. jej najbardziej znaczący bit jest przesunięty za punkt binarny), a wykładnik jest korygowany pod kątem odchylenia.

Od wersji 1.6 java.lang.Math zapewnia również bezpośrednią metodę uzyskania nieobciążonego wykładnika (zwanego getExponent (double))

Jednak liczby, o które prosisz, są częściami całkowitymi i ułamkowymi liczby, które można uzyskać za pomocą

integral = Math.floor(x)
fractional = x - Math.floor(x)

chociaż możesz chcieć inaczej traktować liczby ujemne (floor(-3.5) == -4.0), w zależności od tego, dlaczego potrzebujesz tych dwóch części.

Zdecydowanie sugerowałbym, abyś nie nazywał tych mantys i wykładników.



3

[Edytuj: pierwotnie pytanie dotyczyło sposobu uzyskania mantysy i wykładnika.]

Gdzie n jest liczbą, aby uzyskać prawdziwą mantysę / wykładnik:

exponent = int(log(n))
mantissa = n / 10^exponent

Lub, aby uzyskać odpowiedź, której szukałeś:

exponent = int(n)
mantissa = n - exponent

Nie są to dokładnie Java, ale powinny być łatwe do konwersji.


3

Część całkowita pobierana jest z prostego rzutowania, a na ułamkowy - podział na struny:

double value = 123.004567890

int integerPart = (int) value; // 123

int fractionPart = 
  Integer.valueOf(String.valueOf(value)
      .split(".")[1]); // 004567890

/**
* To control zeroes omitted from start after parsing.
*/
int decimals =
  String.valueOf(value)
      .split(".")[1].length(); // 9

1

A jeśli twój numer to 2.39999999999999. Przypuszczam, że chcesz uzyskać dokładną wartość dziesiętną. Następnie użyj BigDecimal:

Integer x,y,intPart;
BigDecimal bd,bdInt,bdDec;
bd = new BigDecimal("2.39999999999999");
intPart = bd.intValue();
bdInt = new BigDecimal(intPart);
bdDec = bd.subtract(bdInt);
System.out.println("Number : " + bd);
System.out.println("Whole number part : " + bdInt);
System.out.println("Decimal number part : " + bdDec);

0

Ponieważ fmt:formatNumberznacznik nie zawsze daje poprawny wynik, oto inne podejście tylko do JSP: po prostu formatuje liczbę jako ciąg i wykonuje resztę obliczeń na ciągu, ponieważ jest to łatwiejsze i nie wymaga dalszej liczby zmiennoprzecinkowej arytmetyka.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<%
  double[] numbers = { 0.0, 3.25, 3.75, 3.5, 2.5, -1.5, -2.5 };
  pageContext.setAttribute("numbers", numbers);
%>

<html>
  <body>
    <ul>
      <c:forEach var="n" items="${numbers}">
        <li>${n} = ${fn:substringBefore(n, ".")} + ${n - fn:substringBefore(n, ".")}</li>
      </c:forEach>
    </ul>
  </body>
</html>

Po prostu wypróbuj wszystkie liczby z mojego przykładu. fmt:formatNumberzaokrągla argument, co nie jest pożądane w tym przypadku.
Roland Illig,

0

Wiele z tych odpowiedzi ma okropne błędy zaokrąglania, ponieważ rzutują liczby z jednego typu na inny. Co powiesz na:

double x=123.456;
double fractionalPart = x-Math.floor(x);
double wholePart = Math.floor(x);

@justshams A co z używaniem Math.abs?
Stephan

0

Zaakceptowana odpowiedź nie działa dobrze dla liczb ujemnych od -0 do -1,0. Podaj również część ułamkową ujemną.

Na przykład: dla numeru -0,35

zwroty

Część całkowita = 0 Część ułamkowa = -0,35

Jeśli pracujesz ze współrzędnymi GPS, lepiej jest otrzymać wynik ze znakiem na części całkowitej jako:

Część całkowita = -0 Część ułamkowa = 0,35

Te liczby są używane na przykład do współrzędnych GPS, gdzie ważne są znaki dla pozycji szer. Lub długiej

Zaproponuj kod:

    double num;
    double iPart;
    double fPart;

    // Get user input
    num = -0.35d;
    iPart = (long) num;
    //Correct numbers between -0.0 and -1.0
    iPart = (num<=-0.0000001 && num>-1.0)? -iPart : iPart ;
    fPart = Math.abs(num - iPart);
    System.out.println(String.format("Integer part = %01.0f",iPart));
    System.out.println(String.format("Fractional part = %01.04f",fPart));

Wynik:

Integer part = -0
Fractional part = 0,3500


0

Do rozwiązania użyłbym BigDecimal. Lubię to:

    double value = 3.25;
    BigDecimal wholeValue = BigDecimal.valueOf(value).setScale(0, BigDecimal.ROUND_DOWN);
    double fractionalValue = value - wholeValue.doubleValue();

0
String value = "3.06";

if(!value.isEmpty()){
    if(value.contains(".")){    
        String block = value.substring(0,value.indexOf("."));
        System.out.println(block);
    }else{
        System.out.println(value);
    }
}

Ta odpowiedź została oznaczona jako niska jakość. Jeśli odpowiada na pytanie, rozważ dodanie fragmentu tekstu wyjaśniającego, jak to działa.
lmo

0
// target float point number
double d = 3.025;

// transfer the number to string
DecimalFormat df = new DecimalFormat();
df.setDecimalSeparatorAlwaysShown(false);
String format = df.format(d);

// split the number into two fragments
int dotIndex = format.indexOf(".");
int iPart = Integer.parseInt(format.substring(0, dotIndex)); // output: 3
double fPart = Double.parseDouble(format.substring(dotIndex)); // output: 0.025

0

OK, może jest późno, ale myślę, że najlepszym i dokładniejszym podejściem jest użycie BigDecimal

double d = 11.38;

BigDecimal bigD = BigDecimal.valueOf(d);
int intPart = bigD.intValue();
double fractionalPart = bigD.subtract(BigDecimal.valueOf(intPart)).doubleValue();

System.out.println(intPart); // 11
System.out.println(fractionalPart ); //0.38

Jeśli masz podwojenie, ma niedokładność zmiennoprzecinkową. Konwersja na BigDecimal nie przywróci jej w magiczny sposób precyzji.
Taschi

@Taschi Myślę, że chodzi o oddzielenie części int i ułamkowej, a nie o przywrócenie jej precyzji!
Omar Elashry

Omar, mówiłeś konkretnie o swoim podejściu jako „dokładniejszym”, co moim zdaniem jest po prostu nieprawdą. Twoja odpowiedź jest całkowicie do przyjęcia, ale to sformułowanie wydaje mi się mylące, dlatego też ją skomentowałem.
Taschi

@Taschi, powiedziałem, ponieważ w wielu odpowiedziach tracisz wartość, gdy otrzymujesz dane wyjściowe, np. input (5.03) output int = 5 , fractional = 0.0299999Mówimy o wejściach i wyjściach, umieszczasz wartość i odzyskujesz swoją wartość bez utraty 0,001% z niej! i to dokładne, nie wprowadzające w błąd!
Omar Elashry

tak. Tracisz precyzję, gdy przechowujesz coś jako podwójną. Zaokrąglanie podczas konwersji do BigDecimal również traci precyzję. Te dwie straty precyzji mogą się wzajemnie znosić, ale to nie „przywraca” precyzji, ponieważ przywrócenie precyzji jest matematycznie niemożliwe. Nie możesz wyciągać informacji z powietrza.
Taschi

-2
public class MyMain2 {
    public static void main(String[] args) {
        double myDub;
        myDub=1234.5678;
        long myLong;
        myLong=(int)myDub;
        myDub=(myDub%1)*10000;
        int myInt=(int)myDub;
        System.out.println(myLong + "\n" + myInt);
    }
}

Działa to tylko wtedy, gdy liczba ma dokładnie 4 miejsca po przecinku. Nie inaczej.
Markiz Lorne
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.