Modulo Operator ใน Java

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