ข้อความแสดงข้อผิดพลาด "จำนวนเต็มใหญ่เกินไป" สำหรับ 600851475143


89
public class Three {
    public static void main(String[] args) {
        Three obj = new Three();
        obj.function(600851475143);
    }

    private Long function(long  i) {
        Stack<Long> stack = new Stack<Long>();

        for (long j = 2; j <= i; j++) {
            if (i % j == 0) {
                stack.push(j);
            }
        }
        return stack.pop();
    }
}

obj.function(600851475143);เมื่อโค้ดข้างต้นมีการเรียกใช้ก็สร้างข้อผิดพลาดในบรรทัด ทำไม?


1
นอกจากนี้ยังไม่มีความแตกต่างระหว่าง "l" และ "L"?
user446654

@ user446654: ไม่มีครับ อย่างหลังน่าอ่านกว่า อ่าน "Java Puzzler" สำหรับสิ่งนี้
Adeel Ansari

@ user446654: การพัฒนาความคิดของ @Thilo เกี่ยวกับขีด จำกัด หน่วยความจำที่เป็นไปได้เกินฉันต้องการเพิ่ม 2 เหรียญของฉัน: คุณได้เลือกอัลกอริทึมที่แย่มากสำหรับการค้นหาตัวแบ่งทั้งหมดของตัวเลขหากคุณต้องการดำเนินการกับตัวเลขจำนวนมากเช่นในตัวอย่างของคุณ บางสิ่งที่ขึ้นอยู่กับการเขียนโปรแกรมแบบไดนามิกน่าจะทำงานได้ดีกว่า Google เพื่อดูผลลัพธ์ต่อไป
โรมัน

1
เพิ่มแท็ก PE Project Euler # 3
st0le

@ st0le: IMHO คำถามนั้นไม่เกี่ยวกับการแก้ปัญหาดั้งเดิมอย่างแน่นอนและสิ่งที่เราเห็นก็ไม่ใช่วิธีแก้ปัญหาเช่นกัน
โรมัน

คำตอบ:


201

600851475143ไม่สามารถแสดงเป็นจำนวนเต็ม 32 บิต (ชนิดint) สามารถแสดงเป็นจำนวนเต็ม 64 บิต (ชนิดlong) อักษรยาวใน Java ลงท้ายด้วย "L":600851475143L


71

ต่อท้ายคำต่อท้ายL: 23423429L.

ตามค่าเริ่มต้น java จะตีความตัวอักษรตัวเลขทั้งหมดเป็นค่าจำนวนเต็ม 32 บิต หากคุณต้องการระบุอย่างชัดเจนว่านี่คือจำนวนเต็ม 32 บิตที่ใหญ่กว่าคุณควรใช้คำต่อท้ายLสำหรับค่าแบบยาว


สำหรับผู้ที่กำลังมองหาคำอธิบายอย่างละเอียดมากขึ้นว่าเหตุใดคุณจึงได้รับข้อความแสดงข้อผิดพลาดนี้แม้ว่าคุณจะเปลี่ยนประเภทตัวแปรเป็นlongโปรดอ่านสิ่งนี้: stackoverflow.com/a/8924925/293280
Joshua Pinter

29

คุณต้องใช้ลิเทอรัลแบบยาว:

obj.function(600851475143l);  // note the "l" at the end

แต่ฉันคาดว่าฟังก์ชันนั้นจะเต็มหน่วยความจำ (หรือเวลา) ...


17
ถือเป็นแนวทางปฏิบัติที่ดีกว่าในการสร้างตัวlพิมพ์ใหญ่เพื่อให้แยกแยะได้ง่ายจาก1
Bozho

2
@Bozho: เห็นด้วย แต่ฉันมีภูมิหลัง Perl ฉันเขียนโค้ดว่า "เขียนอย่างเดียว" :-)
Thilo

ใช้ "L" แทน "l"
Kevin V

13

คอมไพเลอร์ java พยายามตีความ 600851475143 เป็นค่าคงที่ของชนิด int ตามค่าเริ่มต้น สิ่งนี้ทำให้เกิดข้อผิดพลาดเนื่องจาก 600851475143 ไม่สามารถแสดงด้วย int

หากต้องการบอกคอมไพเลอร์ว่าคุณต้องการให้จำนวนตีความเป็นเวลานานคุณต้องเพิ่มอย่างใดอย่างหนึ่งlหรือLหลังจากนั้น จากนั้นหมายเลขของคุณควรมีลักษณะ600851475143Lดังนี้

เนื่องจากแบบอักษรบางแบบทำให้ยากที่จะแยก "1" และตัวพิมพ์เล็ก "l" ออกจากกันคุณควรใช้ตัวพิมพ์ใหญ่ "L" เสมอ


6

คุณต้องมี 40 บิตเพื่อแทนค่าจำนวนเต็ม 600851475143 ใน Java ค่าจำนวนเต็มสูงสุดคือ 2 ^ 31-1 อย่างไรก็ตาม (เช่นจำนวนเต็มคือ 32 บิตโปรดดูที่ http://download.oracle.com/javase/1.4.2/docs /api/java/lang/Integer.html )

functionนี้มีอะไรจะทำอย่างไรกับ ลองใช้ลิเทอรัลจำนวนเต็มแบบยาวแทน (ตามที่แนะนำในคำตอบอื่น ๆ )


4

ในขณะคอมไพล์หมายเลข "600851475143" จะแสดงเป็นจำนวนเต็ม 32 บิตให้ลองใช้ตัวอักษรยาวแทนที่ท้ายตัวเลขของคุณเพื่อแก้ไขปัญหานี้


3

นอกเหนือจากคำตอบอื่น ๆ แล้วสิ่งที่คุณทำได้คือ:

long l = Long.parseLong("600851475143");

ตัวอย่างเช่น :

obj.function(Long.parseLong("600851475143"));

1

หรือคุณสามารถประกาศหมายเลขอินพุตได้นานแล้วปล่อยให้มันทำรหัสแทงโก้: D ...

public static void main(String[] args) {

    Scanner in = new Scanner(System.in);
    System.out.println("Enter a number");
    long n = in.nextLong();

    for (long i = 2; i <= n; i++) {
        while (n % i == 0) {
            System.out.print(", " + i);
            n /= i;
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.