วิธีการแปลงสองถึงยาวโดยไม่ต้องร่าย?


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
Vitalii Fedorenko

วิธีนี้ ( Double.longValue();) ยังคงมีประโยชน์หากคุณมีค่าสองเท่าจากสิ่งต่าง ๆ เช่นรายการอาร์เรย์เช่นนี้ArrayList<Double>เนื่องจากคุณจะได้รับข้อผิดพลาดที่ไม่สามารถส่งได้ ฉันแค่พูดแบบนี้กับทุกคนที่มาที่นี่และมีปัญหาแตกต่างกันเล็กน้อย
SARose

คำตอบ:


250

สมมติว่าคุณมีความสุขกับการตัดทอนสู่ศูนย์เพียงแค่โยน:

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

นี่จะเร็วกว่าการเรียนผ่าน wrapper - และที่สำคัญกว่านั้นคือสามารถอ่านได้มากขึ้น ตอนนี้ถ้าคุณต้องการปัดเศษอื่นที่ไม่ใช่ "เสมอไปที่ศูนย์" คุณจะต้องใช้รหัสที่ซับซ้อนกว่านี้เล็กน้อย


8
คำตอบที่ยอดเยี่ยม - ส่วนที่เป็นศูนย์จะไม่ถูกต้องสำหรับแอปของฉันดังนั้นปรบมือสำหรับการเน้นในคำตอบของคุณและเตือนให้สมองของฉันเมาค้างเพื่อใช้ Math.round () ที่นี่แทนที่จะเป็นเพียงการคัดเลือก!
Phantomwhale

123

... และนี่คือวิธีการปัดเศษซึ่งไม่ตัดทอน รีบค้นหาในคู่มือ Java API:

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

มันไม่ได้ให้ผลลัพธ์เหมือนกับนักแสดง ดังนั้นมันขึ้นอยู่กับว่าคนรวยต้องการทำอะไร
Cyrille Ka

3
ใช่. มันเป็นความคิดที่นอกเหนือไปจากสิ่งที่จอนกล่าวว่า :)
โยฮันเน Schaub - litb

2
ฉันชอบสิ่งนี้เพราะมันใช้ได้กับวัตถุแบบ Double และ Long มากกว่าแบบดั้งเดิม
themanatuf

58

แนวทางที่ต้องการควรเป็น:

Double.valueOf(d).longValue()

จากเอกสารประกอบDouble (Java Platform SE 7) :

Double.valueOf(d)

ส่งคืนDoubleอินสแตนซ์ที่เป็นตัวแทนของdoubleค่าที่ระบุ หากDoubleไม่จำเป็นต้องใช้อินสแตนซ์ใหม่โดยทั่วไปวิธีนี้ควรใช้ในการตั้งค่าคอนสตรัคDouble(double)เตอร์เนื่องจากวิธีนี้น่าจะให้ประสิทธิภาพพื้นที่และเวลาที่ดีขึ้นอย่างมีนัยสำคัญโดยการแคชค่าที่ร้องขอบ่อย


36

(new Double(d)).longValue() ภายในตัวละครทำการส่งจึงไม่มีเหตุผลที่จะสร้างวัตถุคู่


13

ห้องสมุด Guava Math มีวิธีการที่ออกแบบมาเป็นพิเศษสำหรับการแปลงความยาวเป็นสองเท่า:

long DoubleMath.roundToLong(double x, RoundingMode mode)

คุณสามารถใช้java.math.RoundingModeเพื่อระบุพฤติกรรมการปัดเศษ


7

หากคุณมีความสงสัยอย่างแรงกล้าว่า DOUBLE นั้นยาวและคุณต้องการ

1) รับค่าที่แน่นอนของ EXACT เป็น LONG

2) โยนข้อผิดพลาดเมื่อไม่ใช่ LONG

คุณสามารถลองสิ่งนี้:

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

Long is a subset of Doubleไม่ถูกต้อง จำนวนหลักที่สำคัญสำหรับ Long นั้นมากกว่า Double ดังนั้นข้อมูลบางส่วนที่ถือโดย Long สามารถสูญหายได้เมื่อถูกแปลงเป็น Double ตัวอย่าง = tio.run/…
Thariq Nugrohotomo

4

คุณต้องการที่จะมีการแปลงแบบไบนารีเช่น

double result = Double.longBitsToDouble(394.000d);

2
นี่คือสิ่งที่ตรงกันข้ามกับสิ่งที่ถูกถาม
ลูคัสฟิลลิปส์

@LucasPhillips คุณพูดถูก ฉันต้องอ่านคำถามผิด แต่ฉันจะทิ้งคำตอบไว้เพราะอาจช่วยคนอื่นได้
pvorb


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.