2010-12-10 7 views
78

en Java cuando haces¿La mejor manera de hacer que el módulo de Java se comporte como debería con números negativos?

a % b 

Si a es negativo, se devolverá un resultado negativo, en lugar de envolver en torno a B como debería. ¿Cuál es la mejor manera de arreglar esto? La única forma en que puedo pensar es en

a < 0 ? b + a : a % b 
+10

No hay un comportamiento del módulo "correcto" cuando se trata de números negativos: muchos idiomas lo hacen de esta manera, muchos idiomas lo hacen diferente y algunos idiomas hacen algo completamente diferente. Al menos los dos primeros tienen sus pros y sus contras. – delnan

+3

esto es simplemente extraño para mí. pensé que solo debería volverse negativo si b es negativo. – fent

+1

posible duplicado de [¿Cómo hace java cálculos de módulo con números negativos?] (Http://stackoverflow.com/questions/4403542/how-does-java-do-modulus-calculations-with-negative-numbers) –

Respuesta

110

Se comporta como debería a% b = a - a/b * b; es decir, es el resto.

Puede hacerlo% b


Esta expresión trabaja como resultado de (a % b) (a b% + b) es necesariamente menor que b, no importa si a es positivo o negativo. Agregar b se ocupa de los valores negativos de a, ya que (a % b) es un valor negativo entre -b y 0, (a % b + b) es necesariamente inferior a b y positivo. El último módulo está en el caso a fue positivo para empezar, ya que si a es positivo (a % b + b) sería mayor que b. Por lo tanto, (a % b + b) % b lo vuelve a ser más pequeño que b (y no afecta los valores negativos a).

+3

esto funciona mejor gracias. y funciona para números negativos que son mucho más grandes que b también. – fent

+0

¡esta es una muy buena respuesta! tan cerca de elegante como java te dejará ir, creo que – mfrankli

+0

@PeterLawrey - Gracias, yo también necesitaba esta solución, pero ¿estarías dispuesto a explicar por qué funciona? – Lou

8

Para aquellos que no utilizan (o no poder usar) de Java 8, sin embargo, guayaba vino al rescate con IntMath.mod(), disponible desde 11,0 guayaba.

IntMath.mod(2, 3) = 2 
IntMath.mod(-2, 3) = 1 

Una advertencia: a diferencia de Java 8 Math.floorMod(), el divisor (el segundo parámetro) no puede ser negativa.

5

En teoría de números, el resultado siempre es positivo. Supongo que este no es siempre el caso en los lenguajes de programación porque no todos los programadores son matemáticos. Mis dos centavos, lo consideraría un defecto de diseño del lenguaje, pero no puede cambiarlo ahora.

= MOD (-4.180) = 176 = MOD (176, 180) = 176

porque 180 * (-1) + 176 = -4 igual que 180 * 0 + 176 = 176

Usando el ejemplo de reloj aquí, http://mathworld.wolfram.com/Congruence.html no dirá duration_of_time mod cycle_length es -45 minutos, usted dirá 15 minutos, aunque ambas respuestas satisfacen la ecuación base.

0

prefiero esta expresión:

a < 0 ? b - (-a) % b : a % b 

Esto podría o no podría ser más rápido que la otra fórmula [b% (a b b% +)], ahora que lo pienso de ella. Contiene una rama que generalmente es mala con procesadores modernos, pero usa una operación de módulo menor.

En realidad, definitivamente podría ser más lento.

Cuestiones relacionadas