Jak przekonwertować podwójne na długie bez rzucania?

191

Jaki jest najlepszy sposób na przekształcenie podwójnego w długi bez rzucania?

Na przykład:

double d = 394.000;
long l = (new Double(d)).longValue();
System.out.println("double=" + d + ", long=" + l);
Sanki
źródło
2
po prostu upewnij się, że nie operujesz podwójnymi liczbami większymi niż 2 ^ 54, w przeciwnym razie liczby nie będą pasować do ułamka , więc na przykład wyrażenia takie jak myLong == (long)(myDouble + 1)gdzie myLongrówne myDoublebędą oceniaćtrue
Vitalii Fedorenko
Ta metoda ( Double.longValue();) jest nadal przydatna, jeśli masz podwójne wartości z takich obiektów, jak tablica takich jak ta, ArrayList<Double>ponieważ wystąpi błąd „nie można rzutować”. Mówię to tylko dla każdego, kto tu przyszedł i miał nieco inny problem.
SARose

Odpowiedzi:

250

Zakładając, że jesteś zadowolony ze skrócenia do zera, po prostu użyj:

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

Będzie to szybsze niż przechodzenie przez klasy otoki - a co ważniejsze, jest bardziej czytelne. Teraz, jeśli potrzebujesz zaokrąglania innego niż „zawsze w kierunku zera”, potrzebujesz nieco bardziej skomplikowanego kodu.

Jon Skeet
źródło
8
Świetna odpowiedź - część zmierzająca do zera byłaby błędna dla mojej aplikacji, więc oklaski za podkreślenie tego w twojej odpowiedzi i przypomnienie mojemu kacowi mózgu, aby używał tutaj Math.round () zamiast po prostu rzucać!
Phantomwhale,
123

... A oto sposób zaokrąglania, który się nie przycina. Pospiesz się, aby to sprawdzić w podręczniku Java API Manual:

double d = 1234.56;
long x = Math.round(d); //1235
Johannes Schaub - litb
źródło
Nie daje takiego samego wyniku jak obsada. To zależy od tego, co bogaci chcą robić.
Cyrille Ka
3
Tak. uważano to za dodatek do tego, co powiedział Jon :)
Johannes Schaub - litb
2
Podoba mi się to, ponieważ działa również z obiektami Double i Long, a nie z typami pierwotnymi.
themanatuf
58

Preferowanym podejściem powinno być:

Double.valueOf(d).longValue()

Z dokumentacji Double (Java Platform SE 7) :

Double.valueOf(d)

Zwraca Doubleinstancję reprezentującą określoną doublewartość. Jeśli nowe Doublewystąpienie nie jest wymagane, metoda ta powinna być ogólnie stosowana zamiast konstruktora Double(double), ponieważ metoda ta prawdopodobnie zapewni znacznie lepszą wydajność przestrzeni i czasu dzięki buforowaniu często żądanych wartości.

skacze
źródło
36

(new Double(d)).longValue() wewnętrznie wykonuje rzutowanie, więc nie ma powodu, aby tworzyć obiekt Double.

Michael Myers
źródło
13

Biblioteka Guava Math ma specjalnie zaprojektowaną metodę konwersji podwójnego na długi:

long DoubleMath.roundToLong(double x, RoundingMode mode)

Możesz użyć, java.math.RoundingModeaby określić zachowanie zaokrąglania.

Tyler 傲 来 国 主
źródło
7

Jeśli masz poważne podejrzenia, że ​​PODWÓJNIE jest WIELKIM, i chcesz

1) uzyskaj dojście do wartości DOKŁADNEJ jako DŁUGIE

2) wyrzucić błąd, jeśli nie jest DŁUGI

możesz spróbować czegoś takiego:

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 jest podzbiorem Double, więc możesz uzyskać dziwne wyniki, jeśli nieświadomie spróbujesz przekonwertować Double, który jest poza zasięgiem 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());
}
NS du Toit
źródło
Long is a subset of Doublenie jest dokładne. Liczba cyfr znaczących dla Długiego jest większa niż Podwójna, dlatego niektóre informacje przechowywane w Długim mogą zostać utracone po przekształceniu w Podwójne. Przykład = tio.run/…
Thariq Nugrohotomo
4

Czy chcesz mieć konwersję binarną jak

double result = Double.longBitsToDouble(394.000d);
pvorb
źródło
2
To jest przeciwieństwo tego, o co pytano.
Lucas Phillips
@LucasPhillips Masz rację. Musiałem źle odczytać pytanie, ale zostawię swoją odpowiedź, ponieważ może pomóc innym.
pvorb
1

Po prostu przez następujące:

double d = 394.000;
long l = d * 1L;
devll
źródło
0

Mówiąc prosto, rzutowanie jest bardziej wydajne niż tworzenie obiektu Double.

Vijay Dev
źródło