Qual é a sintaxe do mod em java


231

Como um exemplo no pseudocódigo:

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

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;

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.


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.


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;
}

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!


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


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 );
}

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



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)


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.


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;
}

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


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.


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

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).


-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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.