The Modulo Operator in Java – Java中的摩尔运算符

最后修改: 2018年 10月 17日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’ll learn what the modulo operator is, and how we can use it with Java in some common use cases.

在这个快速教程中,我们将学习什么是模运算,以及我们如何在一些常见的使用情况下用Java使用它。

2. The Modulo Operator

2.摩尔运算符

Let’s start with the shortcomings of simple division in Java.

让我们先来看看Java中简单除法的缺点。

If the operands on both sides of the division operator have type int, the result of the operation is another int:

如果除法运算符两边的操作数的类型是int,则运算的结果是另一个int:

@Test
public void whenIntegerDivision_thenLosesRemainder() {
    assertThat(11 / 4).isEqualTo(2);
}

The same division gives us a different result when at least one of the operands has type float or double:

当至少有一个操作数的类型为floatdouble时,同样的除法会得到不同的结果:

@Test
public void whenDoubleDivision_thenKeepsRemainder() {
    assertThat(11 / 4.0).isEqualTo(2.75);
}

We can observe that we lose the remainder of a division operation when dividing integers.

我们可以观察到,在除以整数时,我们会失去除法运算的剩余部分。

The modulo operator gives us exactly this remainder:

modulo运算符给我们的正是这个余数。

@Test
public void whenModulo_thenReturnsRemainder() {
    assertThat(11 % 4).isEqualTo(3);
}

The remainder is what remains after dividing 11 (the dividend) by 4 (the divisor), which in this case is 3.

余数是11(红利)除以4(除数)后的剩余部分,在本例中是3。

For the same reason a division by zero isn’t possible, it’s not possible to use the modulo operator when the right-side argument is zero.

出于同样的原因,除以0是不可能的,当右边的参数为0时,也不可能使用模运算符。

Both the division and the modulo operation throw an ArithmeticException when we try to use zero as the right side operand:

当我们试图使用0作为右边的操作数时,除法和modulo操作都会抛出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. Common Use Cases

3.常见用例

The most common use case for the modulo operator is to find out if a given number is odd or even.

模运算符最常见的使用情况是找出一个给定的数字是奇数还是偶数。

If the outcome of the modulo operation between any number and two is equal to one, it’s an odd number:

如果任何数字与2之间的模数运算结果等于1,那就是一个奇数。

@Test
public void whenDivisorIsOddAndModulusIs2_thenResultIs1() {
    assertThat(3 % 2).isEqualTo(1);
}

In contrast, if the result is zero (i.e. there’s no remainder), it’s an even number:

相反,如果结果是零(即没有余数),就是一个偶数。

@Test
public void whenDivisorIsEvenAndModulusIs2_thenResultIs0() {
    assertThat(4 % 2).isEqualTo(0);
}

Another good use of the modulo operation is to keep track of the index of the next free spot in a circular array.

摩尔运算的另一个很好的用途是跟踪一个圆形数组中下一个空闲点的索引。

In a simple implementation of a circular queue for int values, the elements are kept in a fixed-size array.

int 值的循环队列的一个简单实现中,元素被保存在一个固定大小的数组中。

Any time we want to push an element to our circular queue, we just compute the next free position by computing the modulo of the number of items we’ve already inserted, plus 1 and the queue capacity:

任何时候我们想把一个元素推到我们的循环队列中,我们只需通过计算我们已经插入的项目数量的模数,加上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;
    }
}

Using the modulo operator, we prevent writeIndex from falling out of the boundaries of the array; therefore, we’ll never get an ArrayIndexOutOfBoundsException.

使用modulo操作符,我们防止writeIndex落入数组的边界;因此,我们永远不会得到ArrayIndexOutOfBoundsException

However, once we insert more than QUEUE_CAPACITY items, the next item will overwrite the first.

然而,一旦我们插入超过QUEUE_CAPACITY项,下一个项目将覆盖第一个项目。

4. Conclusion

4.总结

The modulo operator is used to compute the remainder of an integer division that is otherwise lost.

modulo运算符用于计算整数除法的余数,否则会丢失。

It’s useful for doing simple things, like figuring out if a given number is even or odd, as well as more complex tasks, like tracking the next writing position in a circular array.

它对做简单的事情很有用,比如找出一个给定的数字是偶数还是奇数,以及更复杂的任务,比如跟踪一个圆形数组中的下一个书写位置。

The example code is available in the GitHub repository.

示例代码可在GitHub资源库中找到。