0Pricing
Java Academy · บทเรียน

การคำนวณจำนวนเต็มและโอเวอร์โฟลว์

ทำความเข้าใจการหารจำนวนเต็ม โมดูลัส พฤติกรรมโอเวอร์โฟลว์ และวิธีตรวจจับโอเวอร์โฟลว์

การคำนวณจำนวนเต็มและโอเวอร์โฟลว์ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

การคำนวณจำนวนเต็มและค่าล้น

จำนวนเต็มใน Java มีขนาดตายตัว เมื่อการคำนวณเกินค่าสูงสุดหรือต่ำกว่าค่าต่ำสุด ค่าเหล่านั้นจะ วนกลับโดยไม่มีการแจ้งเตือน และจะไม่เกิดข้อผิดพลาด การทำความเข้าใจเรื่องนี้ช่วยป้องกันข้อผิดพลาดที่ตรวจพบได้ยาก

ช่วงค่าของจำนวนเต็ม

ชนิดจำนวนเต็มแต่ละชนิดมีช่วงค่าจำกัดตามจำนวนบิต:

  • byte: -128 ถึง 127
  • short: -32,768 ถึง 32,767
  • int: -2,147,483,648 ถึง 2,147,483,647
  • long: -9.2 × 10^18 ถึง 9.2 × 10^18
System.out.println(Integer.MAX_VALUE); // 2147483647
System.out.println(Integer.MIN_VALUE); // -2147483648
System.out.println(Long.MAX_VALUE);    // 9223372036854775807
System.out.println(Byte.MAX_VALUE);    // 127

ค่าล้น: การวนกลับอย่างเงียบ ๆ

การบวก 1 ให้กับ Integer.MAX_VALUE จะวนกลับไปเป็น Integer.MIN_VALUE นี่คือการคำนวณแบบส่วนเติมเต็มสอง และ Java ไม่รับประกันผลลัพธ์หรือทำให้เกิดข้อผิดพลาดใด ๆ

int max = Integer.MAX_VALUE;
System.out.println(max + 1); // -2147483648 (overflow!)

byte b = 127;
b++;  // wraps to -128
System.out.println(b); // -128

// Real bug: counting votes in a large election with int
int votes = Integer.MAX_VALUE;
votes += 100; // silently wrong
System.out.println(votes); // negative number!

การตรวจจับค่าล้นด้วย Math.addExact

Java 8+ เพิ่ม Math.addExact(), multiplyExact() และ subtractExact() ซึ่งจะทำให้เกิด ArithmeticException เมื่อค่าล้น แทนที่จะวนกลับโดยไม่มีการแจ้งเตือน

try {
    int result = Math.addExact(Integer.MAX_VALUE, 1);
} catch (ArithmeticException e) {
    System.out.println("Overflow detected!"); // prints this
}

try {
    long safe = Math.multiplyExact(100_000L, 100_000L);
    System.out.println(safe); // 10000000000
} catch (ArithmeticException e) {
    System.out.println("Multiply overflow");
}

การหารจำนวนเต็มและเศษเหลือ

การหารจำนวนเต็มจะตัดเศษเข้าหาศูนย์ ตัวดำเนินการ % ให้เศษเหลือที่มีเครื่องหมายเดียวกับตัวตั้ง โปรดระวังการหารด้วยศูนย์ เพราะจะทำให้เกิด ArithmeticException

System.out.println(10 / 3);    // 3 (not 3.33)
System.out.println(10 % 3);    // 1
System.out.println(-10 % 3);   // -1 (sign follows dividend)
System.out.println(-10 % -3);  // -1

try {
    int x = 5 / 0; // ArithmeticException: / by zero
} catch (ArithmeticException e) {
    System.out.println(e.getMessage()); // / by zero
}

// Float division by zero gives Infinity, not exception
System.out.println(5.0 / 0); // Infinity

การคำนวณด้วย long สำหรับจำนวนขนาดใหญ่

ใช้ long เมื่อค่าอาจเกินช่วงของ int ควรเติม L ต่อท้ายค่าคงที่ long เสมอ เพื่อป้องกันค่าล้นก่อนการกำหนดค่า

// Bug: multiplication done as int, then widened
long wrong = 1_000_000 * 1_000_000;   // overflows int!
System.out.println(wrong); // -727379968 (wrong!)

// Fix: one operand is long
long correct = 1_000_000L * 1_000_000L;
System.out.println(correct); // 1000000000000

// Or cast first
long alsOk = (long) 1_000_000 * 1_000_000;
System.out.println(alsOk); // 1000000000000

ตัวดำเนินการเลื่อนบิต

ตัวดำเนินการเลื่อนบิตเป็นวิธีที่รวดเร็วในการคูณหรือหารด้วยเลขยกกำลังของ 2:

  • n << k — เลื่อนบิตไปทางซ้าย: คูณด้วย 2^k
  • n >> k — เลื่อนบิตไปทางขวาแบบมีเครื่องหมาย: หารด้วย 2^k
  • n >>> k — เลื่อนบิตไปทางขวาแบบไม่มีเครื่องหมาย: เติมด้วย 0
int n = 8;
System.out.println(n << 1);  // 16 (8 * 2)
System.out.println(n << 2);  // 32 (8 * 4)
System.out.println(n >> 1);  // 4  (8 / 2)
System.out.println(n >> 2);  // 2  (8 / 4)

// Check if number is power of 2
boolean isPow2 = n > 0 && (n & (n - 1)) == 0;
System.out.println(isPow2); // true

AND, OR และ XOR ระดับบิต

ตัวดำเนินการระดับบิตทำงานกับบิตแต่ละบิต และใช้ในสิทธิ์การเข้าถึง แฟล็ก และโพรโทคอลระดับล่าง

int a = 0b1010; // 10
int b = 0b1100; // 12

System.out.println(Integer.toBinaryString(a & b)); // 1000 (AND = 8)
System.out.println(Integer.toBinaryString(a | b)); // 1110 (OR  = 14)
System.out.println(Integer.toBinaryString(a ^ b)); // 0110 (XOR = 6)
System.out.println(Integer.toBinaryString(~a));    // ...11110101 (NOT)

// Permission flags example
int READ  = 0b001;
int WRITE = 0b010;
int EXEC  = 0b100;
int perms = READ | WRITE; // user has read+write
System.out.println((perms & EXEC) != 0); // false — no exec

ขีดล่างในค่าคงที่ตัวเลข

Java 7+ อนุญาตให้ใส่ขีดล่างในค่าคงที่ตัวเลขเพื่อให้อ่านง่ายขึ้น คอมไพเลอร์จะไม่สนใจขีดล่างเหล่านี้

int million = 1_000_000;
long creditCard = 4_111_1111_1111_1111L;
double pi = 3.141_592_653_589_793;
int hex = 0xFF_EC_D1_2E;
int binary = 0b0001_0101_0110;

System.out.println(million);   // 1000000
System.out.println(creditCard); // 4111111111111111

BigInteger สำหรับความละเอียดไม่จำกัด

เมื่อค่าเกินขอบเขตของ long ให้ใช้ BigInteger ซึ่งไม่มีค่าล้น แต่ทำงานช้ากว่าชนิดข้อมูลพื้นฐาน ควรใช้กับกุญแจเข้ารหัส แฟกทอเรียล และตัวเลขทางดาราศาสตร์

import java.math.BigInteger;

BigInteger factorial100 = BigInteger.ONE;
for (int i = 2; i <= 100; i++) {
    factorial100 = factorial100.multiply(BigInteger.valueOf(i));
}
System.out.println(factorial100.toString().length() + " digits"); // 158 digits

BigInteger a = new BigInteger("999999999999999999999999999999");
BigInteger b = new BigInteger("1");
System.out.println(a.add(b)); // 1000000000000000000000000000000

ภาคปฏิบัติ: ตัวนับที่ปลอดภัยจากค่าล้น

รูปแบบสำหรับนำตัวนับไปใช้ให้จัดการค่าล้นได้อย่างปลอดภัย โดยใช้ Math.addExact และเปลี่ยนไปใช้ Long.MAX_VALUE เป็นทางเลือกสำรอง

class SafeCounter {
    private long count = 0;

    public void increment() {
        try {
            count = Math.addExact(count, 1L);
        } catch (ArithmeticException e) {
            count = Long.MAX_VALUE; // cap at max
        }
    }

    public long get() { return count; }
}

SafeCounter sc = new SafeCounter();
sc.increment();
sc.increment();
System.out.println(sc.get()); // 2

ตรวจสอบอย่างรวดเร็ว

นิพจน์ต่อไปนี้มีค่าเท่าใด

long result = 1_000_000 * 1_000_000;
System.out.println(result);

ทบทวน: การคำนวณจำนวนเต็มและค่าล้น

ประเด็นสำคัญ:

  • ค่าล้นของจำนวนเต็มจะวนกลับอย่างเงียบ ๆ โดยค่าเริ่มต้นจะไม่มีข้อยกเว้น
  • ใช้ Math.addExact/multiplyExact/subtractExact เพื่อตรวจจับค่าล้น
  • การหารจำนวนเต็มจะตัดเศษเข้าหาศูนย์ ส่วนเครื่องหมายของ % จะเป็นไปตามตัวตั้ง
  • ใช้ค่าคงที่ชนิด long (ส่วนต่อท้าย L) เมื่อผลลัพธ์ระหว่างการคำนวณอาจเกินขอบเขตของ int
  • BigInteger รองรับค่าที่มีขนาดใหญ่ได้โดยไม่เกิดค่าล้น
  • ตัวดำเนินการเลื่อนบิตเป็นทางเลือกที่รวดเร็วแทนการคูณหรือหารด้วยเลขยกกำลังของ 2

คำถามที่พบบ่อย

บทเรียน “การคำนวณจำนวนเต็มและโอเวอร์โฟลว์” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การคำนวณจำนวนเต็มและโอเวอร์โฟลว์” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การคำนวณจำนวนเต็มและโอเวอร์โฟลว์”

ทำความเข้าใจการหารจำนวนเต็ม โมดูลัส พฤติกรรมโอเวอร์โฟลว์ และวิธีตรวจจับโอเวอร์โฟลว์ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การคำนวณจำนวนเต็มและโอเวอร์โฟลว์” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. พื้นฐานสำคัญของคลาส Math
  2. การคำนวณจำนวนเต็มและโอเวอร์โฟลว์
  3. BigDecimal สำหรับการคำนวณทางการเงิน
  4. NumberFormat และ printf
← กลับไปที่ Java Academy