การคำนวณจำนวนเต็มและโอเวอร์โฟลว์
ทำความเข้าใจการหารจำนวนเต็ม โมดูลัส พฤติกรรมโอเวอร์โฟลว์ และวิธีตรวจจับโอเวอร์โฟลว์
การคำนวณจำนวนเต็มและโอเวอร์โฟลว์ เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน
การคำนวณจำนวนเต็มและค่าล้น
จำนวนเต็มใน Java มีขนาดตายตัว เมื่อการคำนวณเกินค่าสูงสุดหรือต่ำกว่าค่าต่ำสุด ค่าเหล่านั้นจะ วนกลับโดยไม่มีการแจ้งเตือน และจะไม่เกิดข้อผิดพลาด การทำความเข้าใจเรื่องนี้ช่วยป้องกันข้อผิดพลาดที่ตรวจพบได้ยาก
ช่วงค่าของจำนวนเต็ม
ชนิดจำนวนเต็มแต่ละชนิดมีช่วงค่าจำกัดตามจำนวนบิต:
byte: -128 ถึง 127short: -32,768 ถึง 32,767int: -2,147,483,648 ถึง 2,147,483,647long: -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^kn >> k— เลื่อนบิตไปทางขวาแบบมีเครื่องหมาย: หารด้วย 2^kn >>> 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); // trueAND, 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); // 4111111111111111BigInteger สำหรับความละเอียดไม่จำกัด
เมื่อค่าเกินขอบเขตของ 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- พื้นฐานสำคัญของคลาส Math
- การคำนวณจำนวนเต็มและโอเวอร์โฟลว์
- BigDecimal สำหรับการคำนวณทางการเงิน
- NumberFormat และ printf