¿Cuál es la sintaxis para mod en java?

231

Como ejemplo en pseudocódigo:

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

Respuestas:

357

En lugar del operador de módulo, que tiene una semántica ligeramente diferente, para enteros no negativos, puede usar el operador restante% . Para su ejemplo exacto:

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

Esto se puede simplificar a una línea:

isEven = (a % 2) == 0;
Cody Hatch
fuente
80
El if / else es innecesario, solo use isEven = (a% 2) == 0,
Steve Kuo
59
Cuidado con los términos mod y modular porque n (mod m) SIEMPRE ES> = 0 pero no n% m. n% m está en el rango> -m y <m. Aunque Java tiene un operador restante para los tipos int y long, no tiene una función de módulo u operador. Es decir, -12% 10 = -2 mientras que -12 mod 10 = 8. Si el operador% devuelve un valor negativo para n% m, entonces (n% m) + m le dará n mod m. BigInteger proporciona funciones para ambos y las especificaciones para ellos explican la diferencia bastante bien. Además, cuidado con cero. En matemáticas, mientras que cero es un número par, NO es positivo ni negativo.
Jim
44
@ nl-x Probablemente porque es mejor ser explícito sobre la precedencia que dejarlo a la convención. Por mi parte, no sabía que %se evalúa antes ==antes de buscarlo, por lo que no estaría claro si la expresión es equivalente a (a%2)==0o a%(2==0). Supongo que es menos importante en Java, donde un booleano no es lo mismo que un número entero
Matthew Sainsbury
8
Este no es el operador de módulo, es el operador restante. Por favor corrija la publicación!
Kieren Johnstone
2
par booleano = ((a & 1) == 0). Más fácil.
mdev
111

Aquí está la representación de su pseudocódigo en código Java mínimo;

boolean isEven = a % 2 == 0;

Ahora lo dividiré en sus componentes. El operador de módulo en Java es el carácter de porcentaje (%). Por lo tanto, tomar un int% int devuelve otro int. El operador de doble igual (==) se utiliza para comparar valores, como un par de entradas y devuelve un valor booleano. Esto se asigna a la variable booleana 'isEven'. Según la precedencia del operador, el módulo se evaluará antes de la comparación.

martinatime
fuente
12
mínimo sería sin los corchetes;)
pstanton
3
Es un operador restante, no un operador de módulo.
Marqués de Lorne
@ user207421 Su nombre es, de hecho, operador de resto, pero no son equivalentes: " módulo - 4. (informática, programación) ¿ Un operador colocado entre dos números, para obtener el resto de la división de esos números"?
GeroldBroser reintegra a Mónica
93

Como todos los demás ya dieron la respuesta, agregaré un poco de contexto adicional. % el operador "módulo" está realmente realizando la operación restante. La diferencia entre mod y rem es sutil, pero importante.

(-1 mod 2) normalmente daría 1. Más específicamente, dados dos enteros, X e Y, la operación (X mod Y) tiende a devolver un valor en el rango [0, Y). Dicho de otra manera, el módulo de X e Y siempre es mayor o igual que cero, y menor que Y.

Realizar la misma operación con el operador "%" o rem mantiene el signo del valor X. Si X es negativo, obtiene un resultado en el rango (-Y, 0]. Si X es positivo, obtiene un resultado en el rango [0, Y).

A menudo, esta sutil distinción no importa. Sin embargo, volviendo a su pregunta de código, hay varias formas de resolver la "uniformidad".

El primer enfoque es bueno para los principiantes, porque es especialmente detallado.

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

El segundo enfoque aprovecha mejor el lenguaje y conduce a un código más sucinto. (No olvide que el operador == devuelve un valor booleano).

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

El tercer enfoque es aquí para completar, y utiliza el operador ternario . Aunque el operador ternario suele ser muy útil, en este caso considero que el segundo enfoque es superior.

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

El cuarto y último enfoque es utilizar el conocimiento de la representación binaria de enteros . Si el bit menos significativo es 0, entonces el número es par. Esto puede verificarse utilizando el operador bit a bit (&). Si bien este enfoque es el más rápido (está haciendo un simple enmascaramiento de bits en lugar de una división), tal vez sea un poco avanzado / complicado para un principiante.

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

Aquí utilicé el operador bit a bit y lo representé en la forma sucinta que se muestra en la opción 2. Reescribirlo en la forma de la Opción 1 (y, alternativamente, la Opción 3) se deja como ejercicio para el lector. ;)

Espero que ayude.

Rob Rolnick
fuente
Gracias Rob Esta confusión causa enormes dificultades para explicar a los programadores cómo implementar algoritmos con propiedades matemáticas de la aritmética modular. El resto NO es un módulo, pero uno puede derivar rápidamente un módulo de los restos.
Jim
1
@TickledPink Excepto que esto no se compila en Java.
Eugene Beresovsky el
33

Para que la operación% (REM) de Java funcione como MOD para valores negativos X e Y positivos, puede usar este método:

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

o con el operador ternario (más corto, pero no posible o menos eficiente en algunas situaciones):

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

Java en realidad no tiene un operador de módulo como C. % en Java es un operador restante. En enteros positivos, funciona exactamente como un módulo, pero funciona de manera diferente en enteros negativos y, a diferencia del módulo, también puede funcionar con números de coma flotante. Aún así, es raro usar% en cualquier cosa que no sean enteros positivos, así que si quieres llamarlo módulo, ¡no dudes en hacerlo!

Greg Charles
fuente
Pero quiero que uno sea un operador de módulo real que también funcione para enteros negativos para que siempre array[x mod array.length]acceda a un elemento en mi matriz en lugar de intentar indexar posiciones negativas.
Kris
2
(x % y + y) % y o comenzando en Java 8,Math.floorMod(x, y)
Greg Charles el
12

Si bien es posible hacer un módulo adecuado comprobando si el valor es negativo y corregirlo si lo es (como muchos han sugerido), existe una solución más compacta.

(a % b + b) % b

Esto primero hará el módulo, limitando el valor al rango -b -> + b y luego agregará b para asegurar que el valor sea positivo, permitiendo que el siguiente módulo lo limite al rango 0 -> b.

Nota: Si b es negativo, el resultado también será negativo.

Stefan T
fuente
Esto puede desbordarse cuando ayb son números grandes, por lo que no es una solución correcta.
Trixie Wolf
11

El código se ejecuta mucho más rápido sin usar módulo:

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

public boolean isOdd(int a){
    return ( (a & 1) == 1 );
}
Miguel
fuente
3
Esto se ve mucho más limpio que la respuesta aceptada. Esto no tiene nada que ver con la optimización prematura. Es simplemente mejor, si funciona.
AlexWien
44
@LluisMartinez Este es uno de los dichos más mal citados en informática. La cita completa es: "Los programadores pierden enormes cantidades de tiempo pensando o preocupándose por la velocidad de las partes no críticas de sus programas, y estos intentos de eficiencia en realidad tienen un fuerte impacto negativo cuando se consideran la depuración y el mantenimiento. Debemos olvidarnos de los pequeños eficiencias, digamos alrededor del 97% del tiempo: la optimización prematura es la raíz de todo mal. Sin embargo, no debemos dejar pasar nuestras oportunidades en ese crítico 3% ". Lo que en realidad significa algo bastante diferente.
Marqués de Lorne
3
@EJP Probablemente tengas razón. Hice una prueba (bucle con 1 millón de iteraciones) tomó 4000 nanosegundos con módulo, 2500 nanosegundos con lógica y.
Lluis Martinez
¿Por qué sería esta una respuesta? Claro que es impar, pero no hace nada con el operador mod / resto. La pregunta habla sobre el operador mod, no sobre cómo encontrar pares impares.
Mark Walsh
5
if (a % 2 == 0) {
} else {
}
JD OConal
fuente
4

En Java es el %operador: 15.17.3. Operador restante%

Tenga en cuenta que también hay floorModen la java.lang.Mathclase que dará un resultado diferente de los %argumentos con diferentes signos:

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

Roland
fuente
1
Upvoted, porque floorMod es un mejor operador de 'módulo' que %porque también funciona correctamente cuando el argumento también es negativo. Ninguna de las otras respuestas es realmente correcta ya que vienen con el descargo de responsabilidad de que% no es realmente módulo a menos que los argumentos sean positivos. En particular, si desea asignar cada número entero a una posición consecutiva en una matriz, entonces array[floorMod(i, array.length)funciona correctamente incluso si el índice ientra en territorio negativo. No es así con %.
Kris
3

Además, mod se puede usar así:

int a = 7;
b = a % 2;

bsería igual a 1. Porque 7 % 2 = 1.

jjnguy
fuente
Probablemente sea un error utilizar operadores compuestos en un ejemplo para principiantes, y sin salida.
Stu Thompson
3

El operador restante en Java es %y el operador de módulo se puede expresar 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
fuente
2

Como otros han señalado, el %operador (resto) no es lo mismo que la modoperación / función del módulo matemático .

mod vs %

La x mod nfunción se asigna xa nen el rango de [0,n).
Mientras que el x % noperador se asigna xa nen el rango de (-n,n).

Para tener un método para usar la operación de módulo matemático y no preocuparnos por el signo que está delante de xuno, puede usar:

((x % n) + n) % n

Tal vez esta imagen ayude a entenderla mejor (tuve dificultades para entender esto primero)

ingrese la descripción de la imagen aquí

m4110c
fuente
1
Bonito dibujo. Otra complejidad: esto no tiene en cuenta la modularidad 2 ^ 32 de la intvariable en sí misma. El floorModmétodo lo hace correctamente (pero es posible que necesite cálculos adicionales si nes negativo).
Maarten Bodewes
1

Otra forma es:

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

Pero la forma más fácil sigue siendo:

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

Como dijo @Steve Kuo.

hermanos28
fuente
0

En Java, la operación mod se puede realizar como tal:

Math.floorMod(a, b)

Nota: La operación de modificación es diferente de la operación restante . En Java, el resto de la operación se puede realizar como tal:

a % b
Shaun Dashjian
fuente
Bueno, no exactamente ... El javadoc de lo Math.floorMod()tiene: 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).por lo tanto, no es exactamente lo mismo que el módulo matemático. Pero , hay una manera de obtener un resultado positivo, también en el Javadoc del mismo 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
@WesternGun Eso puede ser cierto, pero si sabe que el módulo es positivo, entonces la floorModoperación funciona como se esperaba. También hay valores floorModfor longy, de lo contrario, hay BigIntegervalores más grandes.
Maarten Bodewes
-1

El operador del módulo es% (signo de porcentaje). Para probar la uniformidad o generalmente hacer un módulo para una potencia de 2, también puede usar & (el operador y) como isEven =! (A & 1).

jjrv
fuente
-3

Una alternativa al código de @Cody:

Usando el operador de módulo:

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

Creo que este es un código marginalmente mejor que escribir if / else, porque hay menos duplicación y flexibilidad no utilizada. Requiere un poco más de poder mental para examinar, pero el buen nombre de isEvencompensa.

Jay Bazuzi
fuente
2
Es un operador restante, no un operador de módulo.
Marqués de Lorne
@EJP ok. Entonces, ¿cuál es el operador del módulo?
TheRealChx101