Làm thế nào để chuyển đổi gấp đôi thành dài mà không cần đúc?


191

Cách tốt nhất để chuyển đổi gấp đôi thành dài mà không cần đúc là gì?

Ví dụ:

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

2
chỉ cần đảm bảo rằng bạn không hoạt động với số nhân nhiều hơn 2 ^ 54 hoặc các số sẽ không khớp với phân số , vì vậy, ví dụ như các biểu thức như myLong == (long)(myDouble + 1)nơi sẽ đánh giá myLongbằngmyDoubletrue
Vitalii Fedorenko

Phương thức này ( Double.longValue();) vẫn hữu ích nếu bạn có giá trị gấp đôi từ những thứ như danh sách mảng như thế này ArrayList<Double>vì bạn sẽ không thể mắc lỗi. Tôi chỉ nói điều này cho bất cứ ai đến đây và có một vấn đề hơi khác.
SARose

Câu trả lời:


250

Giả sử bạn hài lòng với việc cắt ngắn về 0, chỉ cần chọn:

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

Điều này sẽ nhanh hơn so với việc đi qua các lớp trình bao bọc - và quan trọng hơn, nó dễ đọc hơn. Bây giờ, nếu bạn cần làm tròn số khác với "luôn luôn về không", bạn sẽ cần mã phức tạp hơn một chút.


8
Câu trả lời tuyệt vời - phần không hướng tới sẽ là sai đối với ứng dụng của tôi, vì vậy hãy hoan nghênh làm nổi bật điều này trong câu trả lời của bạn và nhắc nhở bộ não nôn nao của tôi sử dụng Math.round () ở đây thay vì chỉ truyền!
Phantomwhale

123

... Và đây là cách làm tròn mà không cắt ngắn. Nhanh chóng tìm kiếm nó trong Hướng dẫn API Java:

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

Nó không cho kết quả giống như một diễn viên. Vì vậy, nó phụ thuộc vào những gì người giàu muốn làm.
Cyrille Ka

3
vâng nó được coi là một bổ sung cho những gì Jon nói :)
Johannes Schaub - litb

2
Tôi thích điều này vì nó cũng hoạt động với các đối tượng Double và Long hơn là các kiểu nguyên thủy.
themanatuf

58

Cách tiếp cận ưa thích nên là:

Double.valueOf(d).longValue()

Từ tài liệu Double (Nền tảng Java SE 7) :

Double.valueOf(d)

Trả về một Doublethể hiện đại diện cho doublegiá trị được chỉ định . Nếu một Doubletrường hợp mới là không bắt buộc, phương pháp này thường được sử dụng theo sở thích của nhà xây dựng Double(double), vì phương pháp này có khả năng mang lại hiệu suất không gian và thời gian tốt hơn đáng kể bằng cách lưu trữ các giá trị được yêu cầu thường xuyên.


36

(new Double(d)).longValue() bên trong chỉ thực hiện một vai diễn, vì vậy không có lý do gì để tạo một đối tượng Double.


13

Thư viện Guava Math có một phương pháp được thiết kế đặc biệt để chuyển đổi gấp đôi thành dài:

long DoubleMath.roundToLong(double x, RoundingMode mode)

Bạn có thể sử dụng java.math.RoundingModeđể chỉ định hành vi làm tròn.


7

Nếu bạn có một sự nghi ngờ mạnh mẽ rằng NHÂN ĐÔI thực sự là một DÀI, và bạn muốn

1) xử lý giá trị CHÍNH XÁC của nó là DÀI

2) ném lỗi khi nó không phải là DÀI

bạn có thể thử một cái gì đó như thế này:

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 là một tập hợp con của Double, vì vậy bạn có thể nhận được một số kết quả lạ nếu bạn vô tình cố gắng chuyển đổi một Double nằm ngoài phạm vi của 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 Doublekhông chính xác. Số chữ số có nghĩa của Long lớn hơn gấp đôi, do đó một số thông tin do Long nắm giữ có thể bị mất khi chuyển đổi thành Double. Ví dụ = tio.run/ Kẻ
Thariq Nugrohotomo

4

Bạn có muốn có một chuyển đổi nhị phân như

double result = Double.longBitsToDouble(394.000d);

2
Điều này trái ngược với những gì được hỏi.
Lucas Phillips

@LucasPhillips Bạn nói đúng. Tôi đã đọc sai câu hỏi, nhưng tôi sẽ để lại câu trả lời vì nó có thể giúp người khác.
pvorb

1

Đơn giản chỉ bằng cách sau:

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

0

Nói một cách đơn giản, việc truyền hiệu quả hơn là tạo một đối tượng Double.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.