Divisão Python

133

Eu estava tentando normalizar um conjunto de números de -100 a 0 para um intervalo de 10 a 100 e estava tendo problemas apenas para perceber que, mesmo sem variáveis, isso não avalia a maneira como eu esperava:

>>> (20-10) / (100-10)
0

A divisão flutuante também não funciona:

>>> float((20-10) / (100-10))
0.0

Se um dos lados da divisão for convertido em um flutuador, ele funcionará:

>>> (20-10) / float((100-10))
0.1111111111111111

Cada lado do primeiro exemplo é avaliado como int, o que significa que a resposta final será convertida em int. Como 0,111 é menor que 0,5, é arredondado para 0. Não é transparente na minha opinião, mas acho que é assim.

Qual a explicação?

Adam Nelson
fonte
3
Adam, ainda não gosto da sua explicação. O primeiro exemplo é a divisão inteira, que simplesmente retorna 0. O segundo exemplo é colocado entre parênteses incorretamente para o efeito desejado.
Presidente James K. Polk
@ GregS O primeiro exemplo foi o problema. O segundo exemplo é explicativo e foi escrito após a primeira pergunta. Todas as respostas abaixo explicam muito bem o problema, principalmente as do @KennyTM. É importante observar que meu problema original é apenas um problema no Python 2.x, não 3. É um pouco desconcertante que o comportamento mude dessa maneira, mas agora que eu sei, usarei da futura divisão de importação e use o 3 comportamento .x. Felicidades.
Adam Nelson
1
Adam, corrija sua última edição. O lado direito não tem nada de especial; para que uma divisão seja flutuante, o numerador ou o denominador (ou ambos) precisam ser flutuantes. Se você acha que leu nos documentos que o lado direito precisa ser flutuante, a documentação está mal formulada e deve ser corrigida, ou você a entendeu mal. Você viu um exemplo, talvez, e depois extrapolou uma regra?
tzot

Respostas:

246

Você está usando o Python 2.x, onde as divisões inteiras serão truncadas em vez de se tornar um número de ponto flutuante.

>>> 1 / 2
0

Você deve fazer um deles float:

>>> float(10 - 20) / (100 - 10)
-0.1111111111111111

ou from __future__ import division, quais são as forças /para adotar o comportamento do Python 3.x que sempre retorna um float.

>>> from __future__ import division
>>> (10 - 20) / (100 - 10)
-0.1111111111111111
kennytm
fonte
10
Se você usar, from __future__ import divisionpoderá obter o antigo comportamento da divisão no estilo C usando duas barras (por exemplo 1 // 2, resultará em 0). Veja a Pep 238 Alterando o Operador de Divisão
Usuário
1
@Usuário Não é necessário importar de __future__. No Python 2 e 3 //se refere __floordiv__()por padrão.
Casimir
21

Você está colocando números inteiros para que o Python retorne um número inteiro :

>>> 10 / 90
0

Se você converter isso para um float posteriormente, o arredondamento já terá sido feito, em outras palavras, 0 inteiro sempre se tornará 0 float.

Se você usar carros alegóricos em ambos os lados da divisão, o Python fornecerá a resposta que você espera.

>>> 10 / 90.0
0.1111111111111111

Então, no seu caso:

>>> float(20-10) / (100-10)
0.1111111111111111
>>> (20-10) / float(100-10)
0.1111111111111111
Dave Webb
fonte
11

Você precisa alterá-lo para um flutuador antes de fazer a divisão. Isso é:

float(20 - 10) / (100 - 10)
A. Levy
fonte
4
@ Adam Nelson: Funciona corretamente para mim. Verifique seus parênteses.
Fred Larson
Na verdade, estou errado - mas, depois de analisar os documentos, deve-se lançar o lado direito primeiro.
Adam Nelson
10
@ Adam: Não importa de que lado primeiro.
Kennytm
11

No Python 2.7, o /operador é uma divisão inteira se as entradas forem inteiras:

>>>20/15
1

>>>20.0/15.0
1.33333333333

>>>20.0/15
1.33333333333

No Python 3.3, o /operador é uma divisão flutuante, mesmo que as entradas sejam inteiras.

>>> 20/15
1.33333333333

>>>20.0/15
1.33333333333

Para divisão inteira no Python 3, usaremos o //operador

O //operador é um operador de divisão inteira no Python 2.7 e Python 3.3.

No Python 2.7 e Python 3.3:

>>>20//15
1

Agora, veja a comparação

>>>a = 7.0/4.0
>>>b = 7/4
>>>print a == b

Para o programa acima, a saída será False no Python 2.7 e True no Python 3.3.

No Python 2.7, a = 1,75 eb = 1.

No Python 3.3, a = 1,75 eb = 1,75, apenas porque /é uma divisão flutuante.

Harsha Vardhan
fonte
8

Tem a ver com a versão do python que você usa. Basicamente, ele adota o comportamento C: se você dividir dois números inteiros, os resultados serão arredondados para um número inteiro. Lembre-se também de que o Python executa as operações da esquerda para a direita, o que é importante quando você faz a conversão.

Exemplo: Como essa é uma pergunta que sempre aparece na minha cabeça quando estou executando operações aritméticas (devo converter para flutuar e qual número), é apresentado um exemplo desse aspecto:

>>> a = 1/2/3/4/5/4/3
>>> a
0

Quando dividimos números inteiros, não surpreende que ele fique mais baixo.

>>> a = 1/2/3/4/5/4/float(3)
>>> a
0.0

Se digitarmos o último número inteiro a flutuar, ainda obteremos zero, pois no momento em que nosso número é dividido pelo número flutuante já se tornou 0 por causa da divisão do número inteiro.

>>> a = 1/2/3/float(4)/5/4/3
>>> a
0.0

O mesmo cenário acima, mas deslocando o tipo de flutuação um pouco mais perto do lado esquerdo.

>>> a = float(1)/2/3/4/5/4/3
>>> a
0.0006944444444444445

Finalmente, quando tipografamos o primeiro número inteiro a flutuar, o resultado é o desejado, desde o início da primeira divisão, ou seja, a mais à esquerda, usamos flutuadores.

Extra 1: Se você estiver tentando responder a isso para melhorar a avaliação aritmética, verifique este

Extra 2: tenha cuidado com o seguinte cenário:

>>> a = float(1/2/3/4/5/4/3)
>>> a
0.0
George
fonte
4

Especificando um flutuador colocando um '.' após o número também fará com que ele flutue por padrão.

>>> 1 / 2
0

>>> 1. / 2.
0.5
billmanH
fonte
2

Faça pelo menos um deles flutuar, então será a divisão flutuante, não o número inteiro:

>>> (20.0-10) / (100-10)
0.1111111111111111

A transmissão do resultado para flutuar é tarde demais.

incrédulo
fonte
1

Em python cv2não atualizado o cálculo da divisão. portanto, você deve incluir from __future__ import division na primeira linha do programa.

Kavitha Raj
fonte
0

De qualquer maneira, é divisão inteira. 10/90 = 0. No segundo caso, você está apenas convertendo 0 para um float.

Tente converter um dos operandos de "/" para ser um float:

float(20-10) / (100-10)
Fred Larson
fonte
0

Você está flutuando depois que a divisão já aconteceu no seu segundo exemplo. Tente o seguinte:

float(20-10) / float(100-10)
David M
fonte
0

Estou um pouco surpreso que ninguém tenha mencionado que o pôster original poderia ter gostado de números racionais como resultado. Se você estiver interessado nisso, o programa Sage, baseado em Python, estará à sua disposição . (Atualmente ainda é baseado no Python 2.x, embora o 3.x esteja em andamento.)

sage: (20-10) / (100-10)
1/9

Isso não é uma solução para todos, porque faz alguns preparativos para que esses números não sejam ints, mas Integerelementos da classe Sage . Ainda assim, vale a pena mencionar como parte do ecossistema Python.

kcrisman
fonte
0

Pessoalmente, preferi inserir um 1. *no início. Então a expressão se torna algo assim:

1. * (20-10) / (100-10)

Como eu sempre faço uma divisão para alguma fórmula como:

accuracy = 1. * (len(y_val) - sum(y_val)) / len(y_val)

então é impossível simplesmente adicionar um .0like 20.0. E, no meu caso, o empacotamento com a float()pode perder um pouco a legibilidade.

FredWe
fonte