1. ภาพรวม
ในบทช่วยสอนสั้น ๆ นี้เราจะแสดงให้เห็นว่าตัวดำเนินการโมดูโลคืออะไรและเราจะใช้กับ Java สำหรับกรณีการใช้งานทั่วไปได้อย่างไร
2. ตัวดำเนินการ Modulo
เริ่มต้นด้วยข้อบกพร่องของการหารอย่างง่ายใน Java
หากตัวถูกดำเนินการทั้งสองด้านของตัวดำเนินการหารมีประเภทintผลลัพธ์ของการดำเนินการจะเป็นintอื่น:
@Test public void whenIntegerDivision_thenLosesRemainder() { assertThat(11 / 4).isEqualTo(2); }
การหารเดียวกันทำให้เราได้ผลลัพธ์ที่แตกต่างกันเมื่อตัวถูกดำเนินการอย่างน้อยหนึ่งตัวมีประเภทfloatหรือdouble:
@Test public void whenDoubleDivision_thenKeepsRemainder() { assertThat(11 / 4.0).isEqualTo(2.75); }
เราสามารถสังเกตได้ว่าเราสูญเสียส่วนที่เหลือของการดำเนินการหารเมื่อหารจำนวนเต็ม
ตัวดำเนินการโมดูโลให้ส่วนที่เหลือนี้:
@Test public void whenModulo_thenReturnsRemainder() { assertThat(11 % 4).isEqualTo(3); }
ส่วนที่เหลือคือส่วนที่เหลือหลังจากหาร 11 (เงินปันผล) ด้วย 4 (ตัวหาร) - ในกรณีนี้คือ 3
เนื่องจากเหตุผลเดียวกันที่ทำให้หารด้วยศูนย์ไม่ได้จึงไม่สามารถใช้ตัวดำเนินการโมดูโลได้เมื่ออาร์กิวเมนต์ด้านขวาเป็นศูนย์
ทั้งการหารและการดำเนินการโมดูโลจะโยนArithmeticExceptionเมื่อเราพยายามใช้ศูนย์เป็นตัวถูกดำเนินการด้านขวา:
@Test(expected = ArithmeticException.class) public void whenDivisionByZero_thenArithmeticException() { double result = 1 / 0; } @Test(expected = ArithmeticException.class) public void whenModuloByZero_thenArithmeticException() { double result = 1 % 0; }
3. กรณีการใช้งานทั่วไป
กรณีการใช้งานที่พบบ่อยที่สุดสำหรับตัวดำเนินการโมดูโลคือการค้นหาว่าตัวเลขที่กำหนดเป็นเลขคี่หรือคู่
หากผลลัพธ์ของการดำเนินการโมดูโลระหว่างจำนวนใด ๆ และสองเท่ากับหนึ่งมันเป็นจำนวนคี่:
@Test public void whenDivisorIsOddAndModulusIs2_thenResultIs1() { assertThat(3 % 2).isEqualTo(1); }
ในทางกลับกันถ้าผลลัพธ์เป็นศูนย์ (เช่นไม่มีเศษเหลือ) จะเป็นเลขคู่:
@Test public void whenDivisorIsEvenAndModulusIs2_thenResultIs0() { assertThat(4 % 2).isEqualTo(0); }
การใช้งานโมดูโลที่ดีอีกอย่างหนึ่งคือการติดตามดัชนีของจุดว่างถัดไปในอาร์เรย์แบบวงกลม
ในการใช้คิววงกลมสำหรับค่าint อย่างง่ายองค์ประกอบจะถูกเก็บไว้ในอาร์เรย์ขนาดคงที่
เมื่อใดก็ตามที่เราต้องการผลักดันองค์ประกอบไปยังคิววงกลมของเราเราเพียงแค่คำนวณตำแหน่งว่างถัดไปโดยการคำนวณโมดูโลของจำนวนรายการที่เราได้แทรกบวก 1 และความจุของคิว:
@Test public void whenItemsIsAddedToCircularQueue_thenNoArrayIndexOutOfBounds() { int QUEUE_CAPACITY= 10; int[] circularQueue = new int[QUEUE_CAPACITY]; int itemsInserted = 0; for (int value = 0; value < 1000; value++) { int writeIndex = ++itemsInserted % QUEUE_CAPACITY; circularQueue[writeIndex] = value; } }
ใช้ประกอบการโมดูโลที่เราป้องกันไม่ให้writeIndexที่จะหลุดออกจากขอบเขตของอาร์เรย์ดังนั้นเราจะไม่ได้รับการArrayIndexOutOfBoundsException
อย่างไรก็ตามเมื่อเราแทรกรายการมากกว่าQUEUE_CAPACITYรายการถัดไปจะเขียนทับรายการแรก
4. สรุป
ตัวดำเนินการโมดูโลใช้เพื่อคำนวณส่วนที่เหลือของการหารจำนวนเต็มที่เสียไป
เป็นประโยชน์ในการทำสิ่งง่ายๆเช่นการหาว่าตัวเลขที่กำหนดเป็นเลขคู่หรือเลขคี่รวมถึงงานที่ซับซ้อนมากขึ้นเช่นการติดตามตำแหน่งการเขียนถัดไปในอาร์เรย์แบบวงกลม
โค้ดตัวอย่างมีอยู่ในที่เก็บ GitHub