Java中mod的语法是什么?

251

作为伪代码示例:

if ((a mod 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}
17个回答

387

对于非负整数,您可以使用%余数运算符,而不是具有略微不同语义的模运算符。针对您的确切示例:

if ((a % 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}

这可以简化为一行代码:

isEven = (a % 2) == 0;

64
谨慎使用 mod 和 modular 这些术语,因为 n (mod m) 总是>= 0,但不是 n % m。n % m 的范围在>-m且<m之间。尽管Java对于 int 和 long 类型有一个余数运算符,但它没有模函数或运算符。即,-12%10 = -2,而 -12 mod 10 = 8。如果 % 运算符对 n % m 返回一个负值,则 (n % m) + m 将给你 n mod m。BigInteger 提供了这两个函数,并且它们的规范很好地解释了它们的区别。同时要注意零。在数学中,虽然零是一个偶数,但它不是正数或负数。 - Jim
1
为什么在评估 == 0 之前要在括号中放置 a % 2 - nl-x
4
可能是因为明确优先级比恰当的惯例更好。我本人在查阅之前不知道 % 操作符会在 == 操作符之前被计算,所以这个表达式是否等价于 (a%2)==0a%(2==0) 是不清楚的。我猜在 Java 中这个问题不太重要,因为布尔型和整型不同。 - Matthew Sainsbury
10
这不是取模运算符,而是余数运算符。请更正发布内容! - Kieren Johnstone
4
boolean even = ((a & 1) == 0)。这样更简单。 - mdev
在我看来,显式的if/else更容易阅读和扫描(如果开放括号与方法签名在同一行,那么速度会更快,但这毕竟是个人偏好)。但是,如果为了缩短代码而牺牲可读性(考虑三元运算符嵌套),我们不应总是选择“最短”的方式。 - Wolfone

111

以下是您的伪代码用最简单的Java代码表示:

boolean isEven = a % 2 == 0;

现在我将把它分解成其组成部分。Java中的模运算符是百分号(%)。因此,对整数进行取模运算(int % int)会返回另一个整数。双等号(==)运算符用于比较值,例如一对整数,并返回布尔值。然后将其赋值给布尔变量“isEven”。基于运算符优先级,在比较之前会计算取模运算。


12
最简单的方式是不使用括号 ;) - pstanton
4
这是一个取余运算符,而非模运算符。 - user207421
@user207421,它的名字实际上是“余数运算符”,但它们是否等效:“模数 - 4.(计算机,编程)放置在两个数字之间的运算符,以获得这些数字相除的余数。”? - Gerold Broser

98
由于其他人已经给出了答案,我将添加一些额外的上下文。%"模数"运算符实际上执行余数操作。mod和rem之间的区别微妙但重要。
(-1 mod 2)通常会给出1。更具体地说,给定两个整数X和Y,操作(X mod Y) tendsto返回[0,Y)范围内的值。换句话说,X和Y的模数始终大于或等于零,小于Y。
使用“%”或rem运算符执行相同的操作可以保持X值的符号。如果X为负,则得到(-Y,0]范围内的结果。如果X为正,则得到[0,Y)范围内的结果。
通常,这种微妙的区别并不重要。回到您的代码问题,有多种解决“偶数性”的方法。
第一种方法适合初学者,因为它特别冗长。
// Option 1: Clearest way for beginners
boolean isEven;
if ((a % 2) == 0)
{
  isEven = true
}
else
{
  isEven = false
}

第二种方法更好地利用了语言,导致代码更加简洁。(不要忘记 == 运算符返回布尔值。)
// Option 2: Clear, succinct, code
boolean isEven = ((a % 2) == 0);

第三种方法是为了完整性而存在的,使用ternary运算符。虽然三元运算符通常非常有用,但在这种情况下,我认为第二种方法更优。

// Option 3: Ternary operator
boolean isEven = ((a % 2) == 0) ? true : false;

第四种方法是使用整数的二进制表示的知识。如果最低位为0,则该数字为偶数。可以使用按位与运算符(&)进行检查。虽然这种方法最快(只需进行简单的位掩码操作而不是除法),但对于初学者来说可能有点高级/复杂。
// Option 4: Bitwise-and
boolean isEven = ((a & 1) == 0);

这里我使用了按位与运算符,并以选项2中显示的简洁形式表示。将其重写为选项1(或选项3)的形式留给读者作为练习。;)


谢谢你,Rob。这种混淆会给程序员解释如何从模算术中实现具有数学属性的算法带来巨大困难。余数不是模数,但可以从余数快速推导出模数。 - Jim
1
@TickledPink 除了这在Java中无法编译。 - Evgeniy Berezovsky
根据运算符优先级,选项4可以简化为boolean isEven = (a & 1) == 0;。我也想澄清一下我们正在进行位操作,如下所示:boolean isEven = (a & 0x1) == 0;虽然这是个人口味的问题;-) - Hummeling Engineering BV

35

要使Java的%(REM)运算像对于负X和正Y值的MOD一样工作,您可以使用以下方法:

private int mod(int x, int y)
{
    int result = x % y;
    if (result < 0)
    {
        result += y;
    }
    return result;
}

或者使用三元运算符(更短,但在某些情况下不可能或不太有效率):

private int mod(int x, int y)
{
    int result = x % y;
    return result < 0? result + y : result;
}

13

虽然可以通过检查值是否为负并在需要时进行修正(许多人建议的方法)来执行正确的模运算,但有一种更紧凑的解决方案。

(a % b + b) % b

它将首先执行模运算,将值限制在 -b -> +b 范围内,然后添加 b 以确保该值为正数,接下来的模运算将其限制在 0 -> b 范围内。

注意:如果 b 是负数,则结果也将是负数。


当a和b都是大数时,这个方法可能会溢出,因此它不是一个正确的解决方案。 - Trixie Wolf

12

Java中实际上没有像C语言那样的模运算符,%在Java中是一个余数运算符。对于正整数,它的工作方式与模运算完全相同,但对于负整数,它的工作方式不同,并且与模运算不同,它还可以使用浮点数。尽管如此,在任何情况下,使用%除了正整数以外的其他内容都很少见,因此,如果您想称其为模运算符,那么请随意!


但是我想要一个真正适用于负整数的模运算符,这样array[x mod array.length]总是访问我的数组中的一个元素,而不是尝试索引负位置。 - Kris
3
(x % y + y) % y 可以翻译为“将 x 除以 y 的余数加上 y 再对 y 取模”,在 Java 8 中可以使用 Math.floorMod(x, y) 来实现相同的结果。 - Greg Charles

11

不使用模运算会使代码运行速度更快:

public boolean isEven(int a){
    return ( (a & 1) == 0 );
}

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}

3
这看起来比被接受的答案更清晰。这与过早优化无关,只是更好——如果它能够运行。 - AlexWien
4
这是计算机领域最常被误引用的说法之一。完整的引文是“程序员在思考或担忧程序中非关键部分的速度时浪费了大量时间,而这些效率尝试实际上在考虑调试和维护时具有强烈的负面影响。我们应该忘记小小的效率问题,大约97%的情况下应该这样做:过早优化是万恶之源。然而,在关键的3%机会出现时,我们也不应该错过它们。”,这实际上意味着完全不同的事情。 - user207421
3
你可能是对的。我进行了一个测试(使用100万次循环),用取模运算花费了4000纳秒,用逻辑与运算花费了2500纳秒。 - Lluis Martinez
为什么这会是一个答案呢?它确实可以判断奇偶数,但没有使用模运算符。问题谈论的是模运算符,而不是如何找到奇偶数。 - Mark Walsh

6
正如其他人指出的那样,%(余数)运算符与数学中的mod模运算/函数不同。

mod%

x mod n函数将x映射到范围为[0,n)n
x % n运算符将x映射到范围为(-n,n)n

为了使用数学模运算而不关心x前面的符号,可以使用以下方法:

((x % n) + n) % n

也许这张图片能更好地帮助理解(一开始我很难理解这个)。

enter image description here


3
不错的绘画。还有一个复杂性:这并没有考虑到“int”变量本身的2^32模性。 “floorMod”方法确实可以正确地执行此操作(但如果“n”为负,则可能需要进行其他计算)。 - Maarten Bodewes

6

2
点赞,因为floorMod是比%更好的“模”运算符,因为它在参数为负数时也能正常工作。其他答案都不正确,因为它们带有免责声明,即%只有在参数为正数时才是真正的模运算符。特别是,如果您想将每个整数映射到数组中的连续位置,则array[floorMod(i,array.length)即使索引i进入负值领域,也可以正确地工作。但是%就不行。 - Kris

5
if (a % 2 == 0) {
} else {
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接