En java cuando lo hagas
a % b
Si a es negativo, devolverá un resultado negativo, en lugar de ajustarse a b como debería. ¿Cuál es la mejor forma de solucionar este problema? La única forma en que puedo pensar es
a < 0 ? b + a : a % b
java
modulo
negative-number
fingir
fuente
fuente
Respuestas:
Se comporta como debería a% b = a - a / b * b; es decir, es el resto.
Puedes hacer (a% b + b)% b
Esta expresión funciona porque
(a % b)
es necesariamente menor queb
, sin importar sia
es positivo o negativo. La sumab
se ocupa de los valores negativos dea
, ya que(a % b)
es un valor negativo entre-b
y0
,(a % b + b)
es necesariamente menor queb
y positivo. El último módulo está ahí en caso de quea
fuera positivo al principio, ya que sia
es positivo(a % b + b)
se volvería más grande queb
. Por lo tanto, lo(a % b + b) % b
convierte en más pequeño queb
nuevamente (y no afecta losa
valores negativos ).fuente
(a % b)
es necesariamente menor queb
(no importa sia
es positivo o negativo), la sumab
se encarga de los valores negativos dea
, ya que(a % b)
es menor queb
y menor que0
,(a % b + b)
es necesariamente menor queb
y positivo. El último módulo está ahí en caso de quea
fuera positivo para empezar, ya que sia
es positivo(a % b + b)
se volvería más grande queb
. Por lo tanto, lo(a % b + b) % b
convierte en más pequeño queb
nuevamente (y no afecta losa
valores negativos ).a < 0
, tal vez podría echar un vistazo)(a % b + b) % b
se desglosa para valores muy grandes dea
yb
. Por ejemplo, usara = Integer.MAX_VALUE - 1
yb = Integer.MAX_VALUE
dará-3
como resultado, que es un número negativo, que es lo que quería evitar.while
sería más lento si realmente lo necesita, excepto que solo necesita un,if
en cuyo caso es más rápido.A partir de Java 8, puede usar Math.floorMod (int x, int y) y Math.floorMod (long x, long y) . Ambos métodos arrojan los mismos resultados que la respuesta de Peter.
fuente
float
odouble
argumentos. El operador binario Mod (%
) también funciona con operandosfloat
ydouble
.Para aquellos que aún no usan (o no pueden usar) Java 8, Guava vino al rescate con IntMath.mod () , disponible desde Guava 11.0.
Una advertencia: a diferencia de Math.floorMod () de Java 8, el divisor (el segundo parámetro) no puede ser negativo.
fuente
En teoría de números, el resultado siempre es positivo. Supongo que este no es siempre el caso en los lenguajes informáticos porque no todos los programadores son matemáticos. Mis dos centavos, lo consideraría un defecto de diseño del lenguaje, pero no puedes cambiarlo ahora.
= MOD (-4,180) = 176 = MOD (176, 180) = 176
porque 180 * (-1) + 176 = -4 lo mismo que 180 * 0 + 176 = 176
Usando el ejemplo del reloj aquí, http://mathworld.wolfram.com/Congruence.html , no diría que duration_of_time mod cycle_length es -45 minutos, diría que 15 minutos, aunque ambas respuestas satisfacen la ecuación base.
fuente
-1
lugar de,n-1
por ejemplo) entonces hágalo.Java 8 tiene
Math.floorMod
, pero es muy lento (su implementación tiene múltiples divisiones, multiplicaciones y un condicional). Sin embargo, es posible que la JVM tenga un código auxiliar optimizado intrínseco, lo que lo aceleraría significativamente.La forma más rápida de hacer esto sin
floorMod
es como algunas otras respuestas aquí, pero sin ramas condicionales y solo una%
operación lenta .Suponiendo que n es positivo y x puede ser cualquier cosa:
Los resultados cuando
n = 3
:Si solo necesita una distribución uniforme entre
0
yn-1
y no el operador de mod exacto, yx
los suyos no se agrupan cerca0
, lo siguiente será aún más rápido, ya que hay más paralelismo a nivel de instrucción y el%
cálculo lento ocurrirá en paralelo con el otro partes ya que no dependen de su resultado.return ((x >> 31) & (n - 1)) + (x % n)
Los resultados de lo anterior con
n = 3
:Si la entrada es aleatoria en el rango completo de un int, la distribución de ambas soluciones será la misma. Si los grupos de entrada se acercan a cero, habrá muy pocos resultados
n - 1
en la última solución.fuente
Aquí hay una alternativa:
Esto podría ser más rápido o no que la otra fórmula [(a% b + b)% b]. A diferencia de la otra fórmula, contiene una rama, pero usa una operación de módulo menos. Probablemente sea una victoria si la computadora puede predecir un <0 correctamente.
(Editar: se corrigió la fórmula).
fuente