Em java quando você faz
a % b
Se a for negativo, ele retornará um resultado negativo, em vez de voltar para b como deveria. Qual é a melhor maneira de consertar isso? A única maneira de pensar é
a < 0 ? b + a : a % b
java
modulo
negative-number
fent
fonte
fonte
Respostas:
Ele se comporta como deveria a% b = a - a / b * b; ou seja, é o restante.
Você pode fazer (a% b + b)% b
Esta expressão funciona como o resultado de
(a % b)
é necessariamente menor queb
, não importa sea
é positivo ou negativo. Adicionarb
cuida dos valores negativos dea
, já que(a % b)
é um valor negativo entre-b
e0
,(a % b + b)
é necessariamente menor queb
e positivo. O último módulo está lá casoa
fosse positivo para começar, pois sea
fosse positivo(a % b + b)
se tornaria maior queb
. Portanto, o(a % b + b) % b
transforma em menor do queb
novamente (e não afeta osa
valores negativos ).fonte
(a % b)
é necessariamente menor queb
(não importa sea
é positivo ou negativo), a adiçãob
cuida dos valores negativos dea
, pois(a % b)
é menor queb
e menor que0
,(a % b + b)
é necessariamente menor queb
e positivo. O último módulo está lá casoa
fosse positivo para começar, pois sea
fosse positivo(a % b + b)
se tornaria maior queb
. Portanto, o(a % b + b) % b
transforma em menor do queb
novamente (e não afeta osa
valores negativos ).a < 0
, talvez você pudesse dar uma olhada)(a % b + b) % b
divide para valores muito grandes dea
eb
. Por exemplo, usara = Integer.MAX_VALUE - 1
eb = Integer.MAX_VALUE
dará-3
como resultado, que é um número negativo, que é o que você queria evitar.while
seria mais lento se você realmente precisar, exceto que você só precisa de umif
, caso em que é realmente mais rápido.A partir do Java 8, você pode usar Math.floorMod (int x, int y) e Math.floorMod (long x, long y) . Ambos os métodos retornam os mesmos resultados da resposta de Peter.
fonte
float
oudouble
argumentos. O operador binário mod (%
) também funciona com operandosfloat
edouble
.Para aqueles que ainda não usam (ou não podem usar) o Java 8, o Guava veio ao resgate com IntMath.mod () , disponível desde o Guava 11.0.
Uma advertência: ao contrário do Math.floorMod () do Java 8, o divisor (o segundo parâmetro) não pode ser negativo.
fonte
Na teoria dos números, o resultado é sempre positivo. Eu diria que nem sempre é o caso em linguagens de computador, porque nem todos os programadores são matemáticos. Meus dois centavos, eu consideraria um defeito de design da linguagem, mas você não pode mudar isso agora.
= MOD (-4.180) = 176 = MOD (176, 180) = 176
porque 180 * (-1) + 176 = -4 o mesmo que 180 * 0 + 176 = 176
Usando o exemplo do relógio aqui, http://mathworld.wolfram.com/Congruence.html você não diria duration_of_time mod cycle_length é -45 minutos, você diria 15 minutos, embora ambas as respostas satisfaçam a equação básica.
fonte
-1
vez de,n-1
por exemplo) então faça isso.O Java 8 tem
Math.floorMod
, mas é muito lento (sua implementação tem várias divisões, multiplicações e uma condicional). É possível que a JVM tenha um stub otimizado intrínseco para ela, no entanto, o que a aceleraria significativamente.A maneira mais rápida de fazer isso sem
floorMod
é como algumas outras respostas aqui, mas sem ramificações condicionais e apenas uma%
operação lenta .Supondo que n seja positivo, e x pode ser qualquer coisa:
Os resultados quando
n = 3
:Se você só precisa de uma distribuição uniforme entre
0
en-1
e não o operador mod exato, e seux
não agrupa próximo0
, o seguinte será ainda mais rápido, pois há mais paralelismo de nível de instrução e o%
cálculo lento ocorrerá em paralelo com o outro partes, pois não dependem de seu resultado.return ((x >> 31) & (n - 1)) + (x % n)
Os resultados para o acima com
n = 3
:Se a entrada for aleatória em todo o intervalo de um int, a distribuição das duas soluções será a mesma. Se os clusters de entrada próximos de zero, haverá poucos resultados na
n - 1
última solução.fonte
Aqui está uma alternativa:
Isso pode ou não ser mais rápido do que a outra fórmula [(a% b + b)% b]. Ao contrário da outra fórmula, ela contém uma ramificação, mas usa uma operação de módulo a menos. Provavelmente uma vitória se o computador puder prever um <0 corretamente.
(Editar: corrigida a fórmula.)
fonte