Qual é a sintaxe do mod em java

231

Como um exemplo no pseudocódigo:

if ((a mod 2) == 0)
{
    isEven = true;
}
else
{
    isEven = false;
}
Prumo
fonte

Respostas:

357

Em vez do operador módulo, que tem semântica ligeiramente diferente, para números inteiros não negativos, você pode usar o operador restante% . Para seu exemplo exato:

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

Isso pode ser simplificado para uma linha:

isEven = (a % 2) == 0;
Cody Hatch
fonte
80
O if / else é desnecessária, basta usar eIgual = (a% 2) == 0,
Steve Kuo
59
Cuidado com os termos mod e modular porque n (mod m) SEMPRE é> = 0, mas não n% m. n% m está no intervalo> -m e <m. Embora o Java tenha um operador restante para os tipos int e long, ele não possui função ou operador de módulo. Ou seja, -12% 10 = -2 enquanto -12 mod 10 = 8. Se o operador% retornar um valor negativo para n% m, então (n% m) + m fornecerá n mod m. O BigInteger fornece funções para ambos e as especificações para eles explicam bastante bem a diferença. Além disso, cuidado com zero. Em matemática, enquanto zero é um número par, NÃO é positivo ou negativo.
Jim
4
@ nl-x Provavelmente porque é melhor ser explícito sobre precedência do que deixá-lo em convenção. Eu, pelo menos, não sabia que isso %era avaliado antes de ==procurá-lo, portanto não seria claro se a expressão é equivalente a (a%2)==0ou a%(2==0). Eu acho que é menos importante em java onde um booleano não é o mesmo como um inteiro
Matthew Sainsbury
8
Este não é o operador do módulo - é o operador restante. Corrija a postagem!
Kieren Johnstone
2
booleano par = ((a & 1) == 0). Muito facil.
Mdev 11/0318
111

Aqui está a representação do seu pseudocódigo no código Java mínimo;

boolean isEven = a % 2 == 0;

Agora vou dividi-lo em seus componentes. O operador de módulo em Java é o caractere de porcentagem (%). Portanto, pegar um int% int retorna outro int. O operador double equals (==) é usado para comparar valores, como um par de ints e retorna um booleano. Isso é então atribuído à variável booleana 'isEven'. Com base na precedência do operador, o módulo será avaliado antes da comparação.

martinatime
fonte
12
mínimo seria sem os colchetes;)
pstanton 28/09/10
3
É um operador restante, não um operador de módulo.
Marquês de Lorne
@ user207421 Na verdade, seu nome é operador restante, mas não é equivalente: " módulo - 4. (computação, programação) Um operador colocado entre dois números, para obter o restante da divisão desses números."?
GeroldBroser restabelece Monica
93

Como todo mundo já deu a resposta, adicionarei um pouco de contexto adicional. % o operador "módulo" está realmente executando a operação restante. A diferença entre mod e rem é sutil, mas importante.

(-1 mod 2) normalmente forneceria 1. Mais especificamente, dados dois números inteiros, X e Y, a operação (X mod Y) tende a retornar um valor no intervalo [0, Y). Dito de forma diferente, o módulo de X e Y é sempre maior ou igual a zero e menor que Y.

A execução da mesma operação com o operador "%" ou rem mantém o sinal do valor X. Se X for negativo, você obtém um resultado no intervalo (-Y, 0]. Se X é positivo, obtém um resultado no intervalo [0, Y).

Muitas vezes, essa distinção sutil não importa. Voltando à sua pergunta de código, no entanto, existem várias maneiras de resolver a "uniformidade".

A primeira abordagem é boa para iniciantes, porque é especialmente detalhada.

// Option 1: Clearest way for beginners
boolean isEven;
if ((a % 2) == 0)
{
  isEven = true
}
else
{
  isEven = false
}

A segunda abordagem aproveita melhor o idioma e leva a um código mais sucinto. (Não esqueça que o operador == retorna um booleano.)

// Option 2: Clear, succinct, code
boolean isEven = ((a % 2) == 0);

A terceira abordagem está aqui para garantir a integridade e usa o operador ternário . Embora o operador ternário seja frequentemente muito útil, neste caso, considero a segunda abordagem superior.

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

A quarta e última abordagem é usar o conhecimento da representação binária de números inteiros . Se o bit menos significativo for 0, o número será par. Isso pode ser verificado usando o operador bit a bit (&). Embora essa abordagem seja a mais rápida (você está usando máscaras de bits simples em vez de divisão), talvez seja um pouco avançada / complicada para um iniciante.

// Option 4: Bitwise-and
boolean isEven = ((a & 1) == 0);

Aqui, usei o operador bit a bit e o representei da forma sucinta mostrada na opção 2. Reescrevendo-o na forma da opção 1 (e alternativamente na opção 3) é deixado como exercício para o leitor. ;)

Espero que ajude.

Rob Rolnick
fonte
Obrigado Rob. Essa confusão causa enormes dificuldades em explicar aos programadores como implementar algoritmos com propriedades matemáticas da aritmética modular. O restante NÃO é um módulo, mas é possível derivar rapidamente um módulo dos restos.
Jim
1
@TickledPink Exceto que isso não é compilado em Java.
Eugene Beresovsky 9/11/19
33

Para que a operação% (REM) do Java funcione como MOD para valores negativos de X e Y positivos, você pode usar este método:

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

ou com o operador ternário (mais curto, mas não possível ou menos eficiente em algumas situações):

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

Java, na verdade, não possui operador de módulo, como C. % em Java é um operador restante. Em números inteiros positivos, funciona exatamente como o módulo, mas funciona de maneira diferente em números inteiros negativos e, ao contrário do módulo, também pode funcionar com números de ponto flutuante. Ainda assim, é raro usar% em qualquer coisa, exceto números inteiros positivos; portanto, se você quiser chamá-lo de módulo, fique à vontade!

Greg Charles
fonte
Mas eu quero um operador de módulo real que funcione também para números inteiros negativos, para que array[x mod array.length]sempre acesse um elemento da minha matriz em vez de tentar indexar posições negativas.
Kris
2
(x % y + y) % y ou começando em Java 8,Math.floorMod(x, y)
Greg Charles
12

Embora seja possível fazer um módulo adequado, verificando se o valor é negativo e corrigindo-o se for (da maneira que muitos sugeriram), existe uma solução mais compacta.

(a % b + b) % b

Isso fará primeiro o módulo, limitando o valor ao intervalo -b -> + b e adicione b para garantir que o valor seja positivo, permitindo que o próximo módulo o limite ao intervalo 0 -> b.

Nota: Se b for negativo, o resultado também será negativo

Stefan T
fonte
Isso pode estourar quando aeb são números grandes, portanto, não é uma solução correta.
Trixie Wolf
11

O código roda muito mais rápido sem usar o módulo:

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

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}
Michael
fonte
3
Isso parece muito mais limpo que a resposta aceita. Isso não tem nada a ver com otimização prematura. É simplesmente melhor, - se funcionar.
AlexWien
4
@LluisMartinez Este é um dos ditos mais citados incorretamente na computação. A citação completa é "Os programadores perdem muito tempo pensando ou se preocupando com a velocidade das partes não críticas de seus programas, e essas tentativas de eficiência realmente têm um forte impacto negativo quando a depuração e a manutenção são consideradas. Devemos esquecer as pequenas eficiências, digamos, cerca de 97% das vezes: a otimização prematura é a raiz de todo mal. No entanto, não devemos desperdiçar nossas oportunidades nesses 3% críticos ". O que realmente significa algo bem diferente.
Marquês de Lorne #
3
@EJP Você provavelmente está certo. Eu fiz um teste (loop com 1 milhão de iterações) levou 4000 nanossegundos com módulo, 2500 nanossegundos com lógica e.
Lluis Martinez
Por que isso seria uma resposta? Certamente, ele faz pares ímpares, mas não faz nada com o operador mod / restante. A questão fala sobre o operador mod, e não sobre como encontrar pares ímpares.
Mark Walsh
5
if (a % 2 == 0) {
} else {
}
JD OConal
fonte
4

Em Java, é o %operador: 15.17.3. Operador restante%

Observe que também existe floorModna java.lang.Mathclasse que fornecerá um resultado diferente %para argumentos com sinais diferentes:

public static int floorMod​(int x, int y)

Roland
fonte
1
Promovido, porque floorMod é um melhor operador de 'módulo' do %que também funciona corretamente quando o argumento também é negativo. Nenhuma das outras respostas realmente está correta, pois elas vêm com o aviso de que% não é realmente um módulo, a menos que os argumentos sejam positivos. Em particular, se você deseja mapear todos os números inteiros para uma posição consecutiva em uma matriz, array[floorMod(i, array.length)funcionará corretamente, mesmo que o índice ientre em território negativo. Não é assim com %.
Kris
3

Além disso, o mod pode ser usado assim:

int a = 7;
b = a % 2;

bseria igual a 1. Porque 7 % 2 = 1.

jjnguy
fonte
provavelmente é um erro usar operadores compostos em um exemplo para iniciantes e sem saída.
Stu Thompson
3

O operador restante em Java é %e o operador módulo pode ser expresso como

public int mod(int i, int j)
{
  int rem = i % j;
  if (j < 0 && rem > 0)
  {
    return rem + j;
  }
  if (j > 0 && rem < 0)
  {
    return rem + j;
  }
  return rem;
}
eljenso
fonte
2

Como outros já apontaram, o %operador (restante) não é o mesmo que a modoperação / função do módulo matemático .

mod vs %

A x mod nfunção é mapeada xpara nno intervalo de [0,n).
Enquanto o x % noperador mapeia xpara nno intervalo de (-n,n).

Para ter um método para usar a operação do módulo matemático e não se importar com o sinal na frente de xum, pode-se usar:

((x % n) + n) % n

Talvez essa imagem ajude a entendê-la melhor (tive dificuldade em entender isso primeiro)

insira a descrição da imagem aqui

m4110c
fonte
1
Belo desenho. Uma outra complexidade: isso não leva intem conta a modularidade 2 ^ 32 da própria variável. O floorModmétodo faz isso corretamente (mas você pode precisar de cálculos adicionais se nfor negativo).
Maarten Bodewes
1

Outra maneira é:

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

Mas a maneira mais fácil ainda é:

boolean isEven = (a % 2) == 0;

Como o @Steve Kuo disse.

brothers28
fonte
0

Em Java, a operação mod pode ser executada como tal:

Math.floorMod(a, b)

Nota: A operação mod é diferente da operação restante . Em Java, a operação restante pode ser executada como tal:

a % b
Shaun Dashjian
fonte
Bem, não exatamente ... O javadoc Math.floorMod()possui: The floor modulus is x - (floorDiv(x, y) * y), has the same sign as the divisor y, and is in the range of -abs(y) < r < +abs(y).Portanto, não é exatamente o mesmo que módulo matemático. Mas , há uma maneira de obter um resultado positivo, também no Javadoc, do mesmo método:If the signs of arguments are unknown and a positive modulus is needed it can be computed as (floorMod(x, y) + abs(y)) % abs(y).
WesternGun
@ WestestGun Isso pode ser verdade, mas se você souber que o módulo é positivo, a floorModoperação funcionará conforme o esperado. Há também os valores floorModfor longe, caso contrário, há BigIntegervalores maiores.
Maarten Bodewes
-1

O operador do módulo é% (sinal de porcentagem). Para testar a uniformidade ou geralmente fazer o módulo com uma potência de 2, você também pode usar & (o operador e) como isEven =! (A & 1).

jjrv
fonte
-3

Uma alternativa ao código de @Cody:

Usando o operador de módulo:

bool isEven = (a % 2) == 0;

Eu acho que este é um código marginalmente melhor do que escrever if / else, porque há menos duplicação e flexibilidade não utilizada. Requer um pouco mais de poder cerebral para examinar, mas a boa nomeação de isEvencompensa.

Jay Bazuzi
fonte
2
É um operador restante, não um operador de módulo.
Marquês de Lorne #
@EJP ok. Então, qual é o operador do módulo?
TheRealChx101