Come ottengo parti intere e frazionarie da double in JSP / Java?


104

Come ottengo parti intere e frazionarie da double in JSP / Java? Se il valore è 3,25, voglio ottenere fractional =.25,whole = 3

Come possiamo farlo in Java?


4
Sembra che tu abbia un'idea imprecisa di cosa siano mantissa ed esponente. Non sono solo "parte intera" e "parte frazionaria". Vedi en.wikipedia.org/wiki/Floating_point
Jon Skeet

In realtà ho letto circa 5 post prima di dire "hey .. non è chiamato un esponente". Il mio cervello ha buttato fuori le parole e ha iniziato a risolvere il problema .. mi ha dato cattive abitudini leggere cose di programmazione :)
Gishu

1
Si prega inoltre di riformulare la domanda OP .. per i posteri tra le altre ragioni.
Gishu

1
Sembra sospettoso come un problema con i compiti.
Brian Knoblauch

Oh capisco.
Mi

Risposte:


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);

Uscite:

Integer part = 2
Fractional part = 0.2999999999999998

61
In realtà questa pagina è il primo risultato di una ricerca su Google per "ottieni frazionario e parte intera da double java" =)
Chris

12
In realtà questa risposta non è corretta, poiché valori maggiori di long possono rappresentare, darà numeri enormi nella parte frazionaria. La risposta di Dan Vinton di seguito è altrettanto semplice e restituisce sempre il risultato corretto.
arberg

2
quindi in realtà, questo non è corretto, come puoi vedere nell'output. l'input è frazione di 3 e l'output è 29999999 ... usare BigDecimal invece di Double farà il trucco però
Alex

2
@Alex No, l'input è un numero molto vicino 2.3, ma sicuramente no 2.3. E non c'è niente di sbagliato nell'output, a meno che tu non voglia più di 10 cifre valide. Tutto ciò di cui hai bisogno è un po 'di arrotondamento in ogni output (ad esempio, formato %.9f) che di solito è meno doloroso di BigDecimal. L'unico problema qui è l'overflow.
maaartinus

1
La conversione da double a int è quasi sempre una cattiva idea. Perché, ad esempio, per (long)1.0e100te otterrai 0. Molte volte hai bisogno del doppio valore semplicemente "floored" per il quale c'è floor(). Se si desidera utilizzare sia parti integrali che frazionarie modf(). Davvero, questa è una cattiva risposta.
mojuba

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

12
Perché questo è downvoted? Funziona bene e con la mia modifica funzionerà anche con valori negativi.
HRJ

La parte intera potrebbe essere => long longPart = (long) 3.25
jdurango

2
Non funzionerà per neg. valori. Vale a dire -3,25% 1 = 0,75 non 0,25. Quindi integralPart sarà -3,25 - 0,75 = -4.
WindRider

2
@WindRider, ho controllato per negativo .. e funziona .. tuttavia per le cifre decimali che sono di piccolo numero, ci sarà un leggero errore. Ex. per -03.0025 restituisce -0.002499999999999999467 e -3.0
justshams

5
La confusione qui è perché alcuni linguaggi, come Python, usano %per indicare modulo ( -3.25 % 1 == 0.75) e altri, come Java, Fortran, C e C ++, usano %per significare remainder ( -3.25 % 1 == -0.25). WindRider potrebbe averlo digitato in un REPL Python per convenienza, ma quella risposta è fuorviante perché questa domanda riguarda la JVM.
Jim Pivarski

24

Poiché questa domanda di 1 anno è stata sollevata da qualcuno che ha corretto l'oggetto della domanda, e questa domanda è stata contrassegnata con jsp, e nessuno qui è stato in grado di dare una risposta mirata JSP, ecco il mio contributo mirato JSP.

Usa JSTL (basta semplicemente inserire JSTL-1.2.jar in /WEB-INF/lib) fmt taglib. C'è un <fmt:formatNumber>tag che fa esattamente quello che vuoi e in modo abbastanza semplice con l'aiuto di maxFractionDigitse maxIntegerDigitsattributi.

Ecco un SSCCE , copia e incolla e avvialo.

<%@ 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>

Produzione:

Intero: 3

Frazione: 0,25

Questo è tutto. Non c'è bisogno di massaggiarlo con l'aiuto del codice Java grezzo.


8

La domanda originale richiedeva l'esponente e la mantissa, piuttosto che la parte frazionaria e intera.

Per ottenere l'esponente e la mantissa da un doppio puoi convertirlo nella rappresentazione IEEE 754 ed estrarre i bit in questo modo:

long bits = Double.doubleToLongBits(3.25);

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

Il primo bit della mantinssa non è impostato implicitamente a 1, quindi la mantissa dovrebbe essere (bits & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus non era un'uscita ryt Output: esponente 0 e mantissa 2814749767106560 e se scegli urs agnul la mantissa è 0
Vinayak Bevinakatti

Rotto con 4 voti positivi :) Anche se vedo cosa sta cercando di fare il codice smontando il doppio valore ai suoi giunti, il codice non sembra fornire i valori corretti.
Gishu

@agnul: penso che "mantissa" di solito si riferisca solo al valore dei bit. Potresti semplicemente convertirlo nel significato anteponendo (a volte) un bit. Ma secondo Wikipedia, la parola mantissa è ora deprecata a favore di "frazione".
Rasmus Faber

5

Logica principale devi prima trovare quante cifre ci sono dopo il punto decimale.
Questo codice funziona per qualsiasi numero fino a 16 cifre. Se usi BigDecimal puoi eseguirlo solo per un massimo di 18 cifre. metti il ​​valore di input (il tuo numero) alla variabile "num", qui come esempio l'ho codificato.

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);

Amico, questa è una risposta estremamente complicata per un semplice problema. Hai dato un'occhiata alla risposta accettata?
Grey

1
Ora, la persona che ha votato negativamente (non io a proposito), avrebbe dovuto spiegare perché c'era un voto negativo. Questo non è buono. Ma tutti noi abbiamo ottenuto un punteggio di 1 prima o poi.
Grey

2
@ Gray la domanda era di separare 3.25 come "3" e "25", e la risposta accettata non darà mai "25", ma sempre "2599999999"
OnePunchMan

@Gray, so chi lo ha votato negativamente, era un ragazzo di nome Eji (vecchio utente) che prendeva in giro ogni mio commento, risposta e domanda che posto in questo blog. Infine mi lamento al moderatore.
OnePunchMan

2
Questa risposta è molto utile se vuoi la parte frazionaria come numero intero
Guilherme Campos Hazan,

5

La mantissa e l'esponente di un numero a virgola mobile doppia IEEE sono i valori tali che

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

se la mantissa è della forma 0.101010101_base 2 (cioè il suo bit più significativo viene spostato dopo il punto binario) e l'esponente viene regolato per il bias.

Dalla 1.6, java.lang.Math fornisce anche un metodo diretto per ottenere l'esponente non corretto (chiamato getExponent (double))

Tuttavia, i numeri che stai chiedendo sono le parti integrali e frazionarie del numero, che possono essere ottenute utilizzando

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

anche se potresti voler trattare i numeri negativi in ​​modo diverso (floor(-3.5) == -4.0), a seconda del motivo per cui vuoi le due parti.

Suggerisco caldamente di non chiamare questi mantissa ed esponente.


4

Non so se è più veloce ma lo sto usando

float fp = ip % 1.0f;

3

[Modifica: la domanda originariamente chiedeva come ottenere la mantissa e l'esponente.]

Dove n è il numero per ottenere la mantissa / esponente reale:

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

Oppure, per ottenere la risposta che stavi cercando:

exponent = int(n)
mantissa = n - exponent

Questi non sono esattamente Java, ma dovrebbero essere facili da convertire.


3

La parte intera ottiene dal casting semplice e per frazionario - divisione della stringa:

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

E se il tuo numero è 2.39999999999999. Suppongo che tu voglia ottenere il valore decimale esatto. Quindi usa 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

Poiché il fmt:formatNumbertag non fornisce sempre il risultato corretto, ecco un altro approccio solo JSP: formatta semplicemente il numero come stringa ed esegue il resto del calcolo sulla stringa, poiché è più semplice e non richiede ulteriore virgola mobile aritmetica.

<%@ 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>

Prova solo tutti i numeri del mio esempio. fmt:formatNumberarrotonda il suo argomento, che in questo caso non è voluto.
Roland Illig

0

Molte di queste risposte hanno orribili errori di arrotondamento perché trasmettono numeri da un tipo all'altro. Che ne dite di:

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

@justshams E per quanto riguarda l'utilizzo Math.abs?
Stephan

0

La risposta accettata non funziona bene per i numeri negativi compresi tra -0 e -1,0. Assegna anche la parte frazionaria negativa.

Ad esempio: per il numero -0,35

ritorna

Parte intera = 0 Parte frazionaria = -0,35

Se stai lavorando con coordinate GPS è meglio avere un risultato con il segno sulla parte intera come:

Parte intera = -0 Parte frazionaria = 0,35

Questi numeri vengono utilizzati ad esempio per le coordinate GPS, dove è importante il segno per la posizione Lat o Long

Proponi codice:

    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));

Produzione:

Integer part = -0
Fractional part = 0,3500


0

Userei BigDecimal per la soluzione. Come questo:

    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);
    }
}

Questa risposta è stata contrassegnata come di bassa qualità. Se risponde alla domanda, considera l'aggiunta di un po 'di testo per spiegare come funziona.
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, forse è tardi, ma penso che l'approccio migliore e più accurato sia usare 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

Se hai un doppio, ha un'imprecisione del galleggiante. La conversione in un BigDecimal non ripristinerà magicamente la sua precisione.
Taschi

@Taschi penso che la domanda sia sulla separazione della parte int e frazionaria, non sul ripristino della sua precisione!
Omar Elashry,

Omar, hai specificamente parlato del tuo approccio "più accurato", il che penso non sia vero. La tua risposta è del tutto accettabile, ma questa formulazione mi sembra fuorviante, motivo per cui l'ho commentata.
Taschi

@Taschi, l'ho detto perché in molte risposte perdi valore quando ottieni l'output, ad esempio input (5.03) output int = 5 , fractional = 0.0299999, stiamo parlando di input e output, metti valore e recuperi il tuo valore senza perdere lo 0,001% di esso! e questo preciso, non fuorviante!
Omar Elashry,

sì. Perdi precisione quando memorizzi qualcosa come un doppio in primo luogo. Anche l'arrotondamento durante la conversione in un BigDecimal perde precisione. Queste due perdite di precisione possono annullarsi a vicenda, ma ciò non "ripristina" la precisione, perché il ripristino della precisione è matematicamente impossibile. Non puoi estrarre informazioni dal nulla.
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);
    }
}

Funziona solo se il numero ha esattamente 4 cifre decimali. Non altrimenti.
Marchese di Lorne
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.