Comportamento inesperado na divisão inteira

Alerta de versão: esse post foi escrito com base na versão 2 da linguagem Python. Na versão 3, o operador de divisão inteira é o //.

Para quem já estudou um pouco de programação, o seguinte resultado não é surpresa alguma:

>>> 3 / 2
1

Por se tratar de uma divisão de números inteiros, o resultado é truncado em um número inteiro também. Até aí, está tudo dentro do esperado, não? Então, abra um shell Python e teste a seguinte operação:

>>> -3 / 2
-2

Quem imaginava que o resultado seria -1, levante a mão: \o_

Por que -2 ?!

Em Python, a divisão inteira arredonda o resultado para baixo, ou seja, sempre para o menor número inteiro mais próximo. Por exemplo: 3 / 2 seria 1.5, mas o resultado é arredondado para 1 (e não 2), pois 1 < 2. Já no caso de -3 / 2, o resultado seria -1.5, mas por se tratar de uma divisão inteira, ele é arredondado para -2 e não para -1, pois -2 < -1.

Isso não é muito comum nas linguagens de programação. Em C e Java, por exemplo, uma divisão inteira tem o seu resultado sempre arredondado em direção ao 0. Python, como já vimos, faz com que o resultado de uma divisão inteira seja arredondado para baixo. Veja a ilustração abaixo:

drawing

Mas por que Python faz dessa forma? Ninguém melhor para explicar isso do que o criador da linguagem, o Guido Van Rossum. Em um post no blog Python History, ele explica que resultados negativos de divisão inteira são arredondados em direção a -∞ para que a seguinte relação entre as operações de divisão (/) e de módulo (%) se mantenha também para as operações com resultados negativos:

quociente = numerador / denominador
resto = numerador % denominador
denominador * quociente + resto == numerador

Vamos testar?

>>> numerador = -3
>>> denominador = 2
>>> quociente = numerador / denominador
>>> resto = numerador % denominador
>>> print quociente, resto
-2 1
>>> print denominador * quociente + resto == numerador
True
# e agora, com numerador positivo
>>> numerador = 3
>>> quociente = numerador / denominador
>>> resto = numerador % denominador
>>> print quociente, resto
1 1
>>> print denominador * quociente + resto == numerador
True

Perceba que se o resultado fosse arredondado em direção ao zero, a propriedade não seria satisfeita.

Esse é um detalhe de implementação muito importante e que todo desenvolvedor Python deve conhecer para não introduzir bugs em seus códigos, para evitar de perder horas depurando algo que parecia fugir comportamento esperado e também para evitar sentimentos de “esse intepretador está errado!”.

Leia mais sobre o assunto no post do Guido Van Rossum no blog The History of PythonWhy Python’s Integer Division Floors.

3 comentários sobre “Comportamento inesperado na divisão inteira

  1. Pingback: O que mudou no Python 3? | Python Help

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s