Come convertire un doppio in lungo senza casting?


191

Qual è il modo migliore per convertire un doppio in un lungo senza lanciare?

Per esempio:

double d = 394.000;
long l = (new Double(d)).longValue();
System.out.println("double=" + d + ", long=" + l);

2
assicurati solo di non operare con doppi più di 2 ^ 54 o che i numeri non rientrano nella frazione , quindi ad esempio espressioni come myLong == (long)(myDouble + 1)dove valuteranno gli myLongugualimyDoubletrue
Vitalii Fedorenko,

Questo metodo ( Double.longValue();) è ancora utile se hai valori doppi da cose come un arraylist come questo ArrayList<Double>dato che otterrai un errore impossibile da lanciare. Lo dico solo per chiunque sia venuto qui e abbia avuto un problema leggermente diverso.
SARose il

Risposte:


250

Supponendo che tu sia felice di troncare verso zero, basta lanciare:

double d = 1234.56;
long x = (long) d; // x = 1234

Questo sarà più veloce che passare attraverso le classi wrapper - e, soprattutto, è più leggibile. Ora, se hai bisogno di arrotondamenti diversi da "sempre verso zero", avrai bisogno di un codice leggermente più complicato.


8
Ottima risposta - la parte verso zero sarebbe stata sbagliata per la mia app, quindi applausi per averlo evidenziato nella tua risposta e ricordato al mio cervello con i postumi della sbornia di usare Math.round () qui invece di lanciare!
Phantomwhale,

123

... Ed ecco la via arrotondata che non si tronca. Si affrettò a cercarlo nel Manuale dell'API Java:

double d = 1234.56;
long x = Math.round(d); //1235

Non dà lo stesso risultato di un cast. Quindi dipende da cosa i ricchi vogliono fare.
Cyrille Ka,

3
si. è stato pensato come un'aggiunta a ciò che Jon ha detto :)
Johannes Schaub - litb

2
Mi piace dal momento che funziona anche con oggetti Double e Long piuttosto che con tipi primitivi.
themanatuf,

58

L'approccio preferito dovrebbe essere:

Double.valueOf(d).longValue()

Dalla documentazione Double (Java Platform SE 7) :

Double.valueOf(d)

Restituisce Doubleun'istanza che rappresenta il doublevalore specificato . Se Doublenon è richiesta una nuova istanza, questo metodo dovrebbe generalmente essere utilizzato in preferenza rispetto al costruttore Double(double), poiché è probabile che questo metodo produca prestazioni significativamente migliori in termini di spazio e tempo memorizzando nella cache i valori richiesti di frequente.


36

(new Double(d)).longValue() internamente fa solo un cast, quindi non c'è motivo di creare un oggetto Double.


13

La libreria Guava Math ha un metodo appositamente progettato per convertire un doppio in un lungo:

long DoubleMath.roundToLong(double x, RoundingMode mode)

È possibile utilizzare java.math.RoundingModeper specificare il comportamento di arrotondamento.


7

Se hai il forte sospetto che il DOPPIO sia in realtà un LUNGO, e vuoi farlo

1) ottenere una maniglia sul suo valore ESATTO come LUNGO

2) genera un errore quando non è LUNGO

puoi provare qualcosa del genere:

public class NumberUtils {

    /**
    * Convert a {@link Double} to a {@link Long}.
    * Method is for {@link Double}s that are actually {@link Long}s and we just
    * want to get a handle on it as one.
    */
    public static long getDoubleAsLong(double specifiedNumber) {
        Assert.isTrue(NumberUtils.isWhole(specifiedNumber));
        Assert.isTrue(specifiedNumber <= Long.MAX_VALUE && specifiedNumber >= Long.MIN_VALUE);
        // we already know its whole and in the Long range
        return Double.valueOf(specifiedNumber).longValue();
    }

    public static boolean isWhole(double specifiedNumber) {
        // http://stackoverflow.com/questions/15963895/how-to-check-if-a-double-value-has-no-decimal-part
        return (specifiedNumber % 1 == 0);
    }
}

Long è un sottoinsieme di Double, quindi potresti ottenere strani risultati se cerchi inconsapevolmente di convertire un Double che è al di fuori dell'intervallo di Long:

@Test
public void test() throws Exception {
    // Confirm that LONG is a subset of DOUBLE, so numbers outside of the range can be problematic
    Assert.isTrue(Long.MAX_VALUE < Double.MAX_VALUE);
    Assert.isTrue(Long.MIN_VALUE > -Double.MAX_VALUE); // Not Double.MIN_VALUE => read the Javadocs, Double.MIN_VALUE is the smallest POSITIVE double, not the bottom of the range of values that Double can possible be

    // Double.longValue() failure due to being out of range => results are the same even though I minus ten
    System.out.println("Double.valueOf(Double.MAX_VALUE).longValue(): " + Double.valueOf(Double.MAX_VALUE).longValue());
    System.out.println("Double.valueOf(Double.MAX_VALUE - 10).longValue(): " + Double.valueOf(Double.MAX_VALUE - 10).longValue());

    // casting failure due to being out of range => results are the same even though I minus ten
    System.out.println("(long) Double.valueOf(Double.MAX_VALUE): " + (long) Double.valueOf(Double.MAX_VALUE).doubleValue());
    System.out.println("(long) Double.valueOf(Double.MAX_VALUE - 10).longValue(): " + (long) Double.valueOf(Double.MAX_VALUE - 10).doubleValue());
}

Long is a subset of Doublenon è preciso. Il numero di cifre significative per Long è maggiore di Double, quindi alcune informazioni detenute da Long possono andare perse quando vengono convertite in Double. Esempio = tio.run/…
Thariq Nugrohotomo,

4

Vuoi avere una conversione binaria come

double result = Double.longBitsToDouble(394.000d);

2
Questo è l'opposto di ciò che viene chiesto.
Lucas Phillips,

@LucasPhillips Hai ragione. Devo aver letto male la domanda, ma lascerò la mia risposta poiché potrebbe aiutare gli altri.
pvorb,

1

Semplicemente con il seguente:

double d = 394.000;
long l = d * 1L;

0

In poche parole, il casting è più efficiente della creazione di un doppio oggetto.

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.