Как конвертировать двойное в длинное без приведения?

191

Каков наилучший способ конвертировать двойное в длинное без приведения?

Например:

double d = 394.000;
long l = (new Double(d)).longValue();
System.out.println("double=" + d + ", long=" + l);
санки
источник
2
просто убедитесь, что вы не оперируете с двойными числами больше, чем 2 ^ 54, иначе числа не будут вписываться в дробь , например, выражения, такие как, myLong == (long)(myDouble + 1)где будут myLongравныmyDoubletrue
Виталий Федоренко
Этот метод ( Double.longValue();) все еще полезен, если у вас есть двойные значения из таких вещей, как arraylist, как это, ArrayList<Double>так как вы получите ошибку не могу привести. Я просто говорю это для тех, кто приехал сюда и имел немного другую проблему.
SARose

Ответы:

250

Предполагая, что вы довольны усечением до нуля, просто приведите:

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

Это будет быстрее, чем проходить через классы-обертки, и, что более важно, это более читабельно. Теперь, если вам нужно округление, отличное от «всегда к нулю», вам понадобится немного более сложный код.

Джон Скит
источник
8
Отличный ответ - часть, близкая к нулю, была бы неправильной для моего приложения, поэтому аплодисменты за то, что они выделили это в своем ответе и напомнили моему похмельному мозгу, что нужно использовать Math.round () вместо того, чтобы просто читать!
Призрачный кит
123

... А вот способ округления, который не усекается. Поспешил посмотреть это в Java API Manual:

double d = 1234.56;
long x = Math.round(d); //1235
Йоханнес Шауб - Литб
источник
Это не дает тот же результат, что и актеры. Так что это зависит от того, что хочет сделать богатый.
Сирил Ка
3
Да. это было
задумано
2
Мне это нравится, поскольку он также работает с объектами Double и Long, а не с примитивными типами.
themanatuf
58

Предпочтительный подход должен быть:

Double.valueOf(d).longValue()

Из документации Double (Java Platform SE 7) :

Double.valueOf(d)

Возвращает Doubleэкземпляр, представляющий указанное doubleзначение. Если новый Doubleэкземпляр не требуется, этот метод обычно следует использовать в предпочтении перед конструктором Double(double), поскольку этот метод, вероятно, даст значительно лучшую производительность в пространстве и времени за счет кэширования часто запрашиваемых значений.

leogps
источник
36

(new Double(d)).longValue() внутренне просто выполняет приведение, поэтому нет причин создавать объект Double.

Майкл Майерс
источник
13

В библиотеке Guava Math есть метод, специально разработанный для преобразования двойного в длинное:

long DoubleMath.roundToLong(double x, RoundingMode mode)

Вы можете использовать, java.math.RoundingModeчтобы указать поведение округления.

Тайлер 傲 来 国 主
источник
7

Если у вас есть сильное подозрение, что ДВОЙНОЙ на самом деле долго, и вы хотите

1) получить указатель на его точное значение как долгое

2) выбросить ошибку, когда это не долго

Вы можете попробовать что-то вроде этого:

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 - это подмножество Double, поэтому вы можете получить некоторые странные результаты, если неосознанно попытаетесь конвертировать Double вне диапазона 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
источник
Long is a subset of Doubleне является точным. Число значащих цифр для Long больше Double, поэтому некоторая информация, хранящаяся в Long, может быть потеряна при преобразовании в Double. Пример = tio.run/…
Тарик Нугрохотомо
4

Это противоположно тому, что спрашивают, но, тем не менее, это может оказаться полезным для других:

Вы хотите иметь двоичное преобразование, как?

double result = Double.longBitsToDouble(394.000d);
pvorb
источник
2
Это противоположно тому, что просят.
Лукас Филлипс
@ LucasPhillips Ты прав. Должно быть, я неправильно прочитал вопрос, но я оставлю свой ответ, поскольку он может помочь другим.
pvorb
1

Просто следующим:

double d = 394.000;
long l = d * 1L;
devll
источник
0

Проще говоря, приведение более эффективно, чем создание объекта Double.

Виджей Дев
источник