operação de módulo com valores negativos - coisa estranha?

votos
15

Você pode por favor me diga o quanto é (-2) % 5? De acordo com meu intérprete Python é 3, mas você tem uma explicação sensata para isso?

Eu li que em algumas línguas o resultado pode ser dependente da máquina, mas não tenho certeza embora.

Publicado 04/09/2008 em 14:36
fonte usuário
Em outras línguas...                            


12 respostas

votos
16

A propósito: a maioria das linguagens de programação discordaria Python e dar o resultado -2. Dependendo da interpretação do módulo este está correcto. No entanto, o mais acordado estados definição matemática de que o módulo de um e b é o (estritamente positivo) resto r da divisão de um / b . Mais precisamente, 0 <= r < b por definição.

Respondeu 04/09/2008 em 14:46
fonte usuário

votos
12

O resultado da operação de módulo on negativos parece estar a linguagem de programação dependentes e aqui é uma lista http://en.wikipedia.org/wiki/Modulo_operation

Respondeu 04/09/2008 em 14:41
fonte usuário

votos
11

O seu interpretador Python é correcta. Uma forma (burro) de cálculo de um módulo é subtrair ou adicionar o módulo até que o valor resultante é entre 0 e (módulo - 1).

por exemplo: 13 mod 5 = (13 - 5) mod 5 = (13-10) mod 5 = 3

ou no seu caso: modificação -2 mod 5 = (-2 + 5) 5 = 3

Respondeu 04/09/2008 em 14:40
fonte usuário

votos
6

Como diz a documentação em operações aritméticas binárias , Python assegura que:

Os operadores de divisão inteira e de módulo são conectados pela seguinte identidade: x == (x/y)*y + (x%y). Divisão inteira e módulo também estão conectados com o DIVMOD função interna (): divmod(x, y) == (x/y, x%y).

E, na verdade,

>>> divmod(-2, 5)
(-1, 3).

Outra maneira de visualizar a uniformidade do presente método é a de calcular divmodpara um pequeno número de sequência:

>>> for number in xrange(-10, 10):
...     print divmod(number, 5)
...
(-2, 0)
(-2, 1)
(-2, 2)
(-2, 3)
(-2, 4)
(-1, 0)
(-1, 1)
(-1, 2)
(-1, 3)
(-1, 4)
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(1, 4)
Respondeu 11/07/2010 em 23:18
fonte usuário

votos
4

Como explicado em outras respostas, existem muitas opções para uma operação de módulo com valores negativos. Em línguas diferentes gerais (e diferentes arquiteturas de máquinas) dará um resultado diferente.

De acordo com o manual de referência Python ,

O operador módulo sempre produz um resultado com o mesmo sinal que o seu segundo operando (ou zero); o valor absoluto do resultado é estritamente menor que o valor absoluto do segundo operando.

é a escolha tomada pelo Python. Basicamente módulo é definido de modo a que este sempre contém:

x == (x/y)*y + (x%y)

por isso, faz sentido que (-2)% 5 = -2 - (-2/5) * 5 = 3

Respondeu 04/09/2008 em 15:25
fonte usuário

votos
4

Bem, 0% 5 deve ser 0, certo?

-1% 5 deve ser 4, porque isso é o dígito seguinte permitiu a ir na direcção inversa (ou seja, não pode ser 5, uma vez que está fora do intervalo).

E percorrendo por essa lógica, -2 deve ser 3.

A maneira mais fácil de pensar em como vai funcionar é que você continua adicionando ou subtraindo 5 até que o número cai entre 0 (inclusive) e 5 (exclusive).

Eu não tenho certeza sobre a dependência da máquina - Eu nunca vi uma implementação que era, mas eu não posso dizer que nunca fez.

Respondeu 04/09/2008 em 14:41
fonte usuário

votos
0

Parece haver uma confusão comum entre os termos "módulo" e "resto".

Em matemática, um resto deve sempre ser definido de acordo com o quociente, de modo que, se a / b == c rem dseguida (c * b) + d == a. Dependendo de como você completar o seu quociente, você tem diferentes remanescentes.

No entanto, modulo deve sempre dar um resultado 0 <= r < divisor, que só é consistente com a divisão round-a-menos-infinito se você permitir inteiros negativos. Se divisão arredonda para zero (o que é comum), módulo e restante só são equivalentes para valores não-negativos.

Algumas línguas (nomeadamente C e C ++) não definem os comportamentos / restante arredondamento necessários e %é ambíguo. Muitos definir o arredondamento como para zero, ainda usar o modulo termo onde restante seria mais correto. Python é relativamente invulgar na medida em que arredonda para o infinito negativo, de modo módulo e restante são equivalentes.

Ada arredonda em direção IIRC zero, mas tem tanto mode remoperadores.

A política de C se destina a permitir que os compiladores para escolher a implementação mais eficiente para a máquina, mas IMO é uma falsa otimização, pelo menos nos dias de hoje. Um bom compilador provavelmente será capaz de usar a equivalência para a otimização sempre que um número negativo não pode ocorrer (e quase certamente se você usar tipos não assinados). Por outro lado, onde os números negativos podem ocorrer, você quase certamente se preocupam com os detalhes - por razões de portabilidade você tem que usar algoritmos e / ou cheques overcomplex muito cuidadosamente projetado para garantir que você obtenha os resultados que você quer, independentemente do arredondamento e restante comportamento.

Em outras palavras, o ganho para este "otimização" é principalmente (se não sempre) uma ilusão, ao passo que existem custos muito reais, em alguns casos - por isso é uma falsa otimização.

Respondeu 05/03/2011 em 12:16
fonte usuário

votos
0

Tenha cuidado para não contar com esse comportamento modificação em C / C ++ em todos os sistemas operacionais e arquiteturas. Se bem me lembro, eu tentei confiar em código C / C ++ como

float x2 = x % n;

para manter x2 na faixa de 0 a n-1, mas números negativos rastejou em quando eu ia compilar em um sistema operacional, mas as coisas iriam funcionar bem em outro sistema operacional. Isso fez para um tempo de depuração do mal, uma vez que só aconteceu metade do tempo!

Respondeu 04/09/2008 em 15:46
fonte usuário

votos
0

Uma explicação pode ser que os números negativos são armazenados usando complemento de 2 . Quando o interpretador python tenta fazer a operação de módulo que converte em valor sem sinal. Como tal, em vez do fazer (-2)% 5 que, na verdade, calcula 0xFFFF_FFFF_FFFF_FFFD% 5, que é três.

Respondeu 04/09/2008 em 15:12
fonte usuário

votos
0

O resultado depende do idioma. Python devolve o sinal do divisor, onde por exemplo C # devolve o sinal do dividendo (isto é. 5 -2% -2 retornos em C #).

Respondeu 04/09/2008 em 14:53
fonte usuário

votos
0

É, de facto 3. Em aritmética modular , um módulo é simplesmente o resto de uma divisão, e o restante de -2 5 é dividido por três.

Respondeu 04/09/2008 em 14:41
fonte usuário

votos
0

Bem, -2 dividido por 5 seria 0 com um resto de 3. Não acredito que deve ser muito dependente de plataforma, mas eu já vi coisas estranhas.

Respondeu 04/09/2008 em 14:41
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more