Como posso forçar a divisão a ser ponto flutuante? Divisão continua arredondando para 0?

721

Eu tenho dois valores inteiros ae b, mas preciso da proporção deles em ponto flutuante. Eu sei disso a < be quero calcular a / b, portanto, se eu usar a divisão inteira, sempre receberei 0 com o restante a.

Como forçar ca ser um número de ponto flutuante no Python a seguir?

c = a / b
Nathan Fellman
fonte
Atualize para o Python 3.
Boris

Respostas:

807

No Python 2, a divisão de duas entradas produz um int. No Python 3, ele produz um float. Podemos obter o novo comportamento importando de __future__.

>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663
Michael Fairley
fonte
13
Observe que from __future__ import divisiondeve estar no início do arquivo
yannis
Além disso, o problema é se você quer a divisão inteira em um único lugar, mas a divisão flutuador em outro lugar do arquivo ...
mercury0114
1
@ mercury0114: Não é um problema; você apenas usa //quando deseja divisão de piso e /quando deseja floatdivisão "true" ( ).
ShadowRanger
715

Você pode lançar para flutuar fazendo c = a / float(b). Se o numerador ou o denominador for flutuante, o resultado será também.


Uma ressalva: como os comentaristas apontaram, isso não funcionará se bfor algo diferente de um número inteiro ou de ponto flutuante (ou uma string representando um). Se você estiver lidando com outros tipos (como números complexos), precisará verificar esses ou usar um método diferente.

Steve Trout
fonte
195

Como forçar a divisão a ser ponto flutuante no Python?

Eu tenho dois valores inteiros aeb, mas preciso da proporção deles em ponto flutuante. Eu sei que a <be quero calcular a / b, portanto, se eu usar a divisão inteira, sempre receberei 0 com o restante de a.

Como forçar c para ser um número de ponto flutuante no Python a seguir?

c = a / b

O que realmente está sendo perguntado aqui é:

"Como forço uma divisão verdadeira que a / bretornará uma fração?"

Atualize para o Python 3

No Python 3, para obter uma divisão verdadeira, basta fazê-lo a / b.

>>> 1/2
0.5

A divisão de piso, o comportamento clássico de divisão para números inteiros, agora é a // b:

>>> 1//2
0
>>> 1//2.0
0.0

No entanto, você pode ficar preso no Python 2 ou escrever um código que deve funcionar nos 2 e 3.

Se estiver usando Python 2

No Python 2, não é tão simples. Algumas maneiras de lidar com a clássica divisão Python 2 são melhores e mais robustas que outras.

Recomendação para Python 2

Você pode obter o comportamento de divisão do Python 3 em qualquer módulo com a seguinte importação na parte superior:

from __future__ import division

que aplica a divisão de estilos do Python 3 a todo o módulo. Também funciona em um shell python a qualquer momento. No Python 2:

>>> from __future__ import division
>>> 1/2
0.5
>>> 1//2
0
>>> 1//2.0
0.0

Esta é realmente a melhor solução, pois garante que o código do seu módulo seja mais compatível com o Python 3.

Outras opções para Python 2

Se você não deseja aplicar isso a todo o módulo, estará limitado a algumas soluções alternativas. O mais popular é coagir um dos operandos a flutuar. Uma solução robusta é a / (b * 1.0). Em um shell Python novo:

>>> 1/(2 * 1.0)
0.5

Também robusto é truedivdo operatormódulo operator.truediv(a, b), mas é provavelmente mais lento porque é uma chamada de função:

>>> from operator import truediv
>>> truediv(1, 2)
0.5

Não recomendado para Python 2

Comumente visto é a / float(b). Isso gerará um TypeError se b for um número complexo. Como a divisão com números complexos é definida, faz sentido para mim não ter falha na divisão quando passou um número complexo para o divisor.

>>> 1 / float(2)
0.5
>>> 1 / float(2j)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float

Não faz muito sentido para mim propositadamente tornar seu código mais frágil.

Você também pode executar o Python com o -Qnewsinalizador, mas isso tem a desvantagem de executar todos os módulos com o novo comportamento do Python 3, e alguns de seus módulos podem esperar uma divisão clássica, por isso não recomendo isso, exceto para testes. Mas para demonstrar:

$ python -Qnew -c 'print 1/2'
0.5
$ python -Qnew -c 'print 1/2j'
-0.5j
Aaron Hall
fonte
3
"1 // 2 = 0", "1 // 2,0 = 0,0" - uma pequena pegada interessante, mesmo que seja uma divisão inteira, se algum dos operandos for flutuante, o resultado é um número inteiro, mas também flutuante. Eu estava usando uma divisão inteira para calcular um índice de lista e obter um erro por causa disso.
R. Navega
134
c = a / (b * 1.0)
Pinochle
fonte
66

No Python 3.x, a única barra ( /) sempre significa divisão verdadeira (não truncante). (O //operador é usado para truncar a divisão.) No Python 2.x (2.2 e superior), você pode obter esse mesmo comportamento colocando um

from __future__ import division

na parte superior do seu módulo.

newacct
fonte
30

Apenas a criação de qualquer um dos parâmetros para divisão no formato de ponto flutuante também produz a saída em ponto flutuante.

Exemplo:

>>> 4.0/3
1.3333333333333333

ou,

>>> 4 / 3.0
1.3333333333333333

ou,

>>> 4 / float(3)
1.3333333333333333

ou,

>>> float(4) / 3
1.3333333333333333
gsbabil
fonte
4
Mas você pode ser tentado a fazer 1.0 + 1/3ou float(c) + a/bou mais tarde float(a/b)e ficará desapontado com a resposta. Melhor usar o python 3+ ou importar o __future__.divisionmódulo (veja a resposta aceita), para obter sempre a resposta que você espera. As regras de divisão existentes criam um erro matemático insidioso e difícil de rastrear.
hobs
@JoeCondron Você tentou python -c 'a=10; b=3.0; print a/b'?
gsbabil
Eu não precisava, porque obviamente funciona nesse cenário. No entanto, ae se e 'b', por exemplo, as saídas de uma função de valor inteiro? Por exemplo a = len(list1), b = len(list2),.
JoeCondron
@ JoeCondron: bom ponto. Acabei de atualizar a resposta para incluir float(..). Eu acho que multiplicar 1.0, como @Pinochle sugeriu abaixo, também pode ser útil.
gsbabil
21

Adicione um ponto ( .) para indicar números de ponto flutuante

>>> 4/3.
1.3333333333333333
Alexander
fonte
2
Como você aplicará essa abordagem se o numerador e o denominador forem variáveis?
stackoverflowuser2010
Presumo que você se refira ao primeiro exemplo, se for assim, eu usaria apenas float()uma das variáveis.
Alexander
13

Isso também vai funcionar

>>> u=1./5
>>> print u
0.2
Gaurav Agarwal
fonte
4
E como você aplicará essa abordagem se o numerador e o denominador forem variáveis?
stackoverflowuser2010
1
Porque não funciona quando variáveis ​​são usadas para abstração. Quase nenhum código significativo possui valores codificados dessa maneira.
Keir Simmons
1
Isso tem poucos votos porque esta resposta não responde à pergunta e não é uma resposta geral. Em uma resposta, também é importante primeiro mostrar por que isso funciona. É muito simples: se o numerador ou denominador for um flutuador, o resultado será um flutuador. Normalmente você não usa python como uma calculadora de texto simples, então você quer uma resposta para variáveis ae b.
TimZaman
Durante muito tempo, pensei que ./era um operador válido em python que permite fazer a divisão de ponto flutuante. É por isso que é bom para usar espaço em branco judiciosamente, em qualquer linguagem de programação
smac89
6

Se você deseja usar a divisão "true" (ponto flutuante) por padrão, há um sinalizador de linha de comando:

python -Q new foo.py

Existem algumas desvantagens (do PEP):

Argumentou-se que uma opção de linha de comando para alterar o padrão é ruim. Certamente pode ser perigoso nas mãos erradas: por exemplo, seria impossível combinar um pacote de biblioteca de terceiros que exija -Qnew com outro que exija -Qold.

Você pode aprender mais sobre os outros valores de sinalizadores que alteram / alertam sobre o comportamento da divisão, consultando a página de manual python.

Para detalhes completos sobre as mudanças de divisão, leia: PEP 238 - Mudando o Operador de Divisão

stephenbez
fonte
2
from operator import truediv

c = truediv(a, b)
JoeCondron
fonte
2
Porém, isso não é ideal, pois não funciona no caso de aint e bfloat. Uma solução melhor na mesma linha é fazer from operator import truedive usar truediv(a, b).
Marque Dickinson
Sim você está certo. Eu estava assumindo os dois números inteiros, pois esse é o único momento em que as operações da divisão diferem, mas você realmente deseja uma solução geral. Na verdade, eu não sabia que você poderia importar o operador ou que ele não funciona em divisores flutuantes. Resposta editada.
JoeCondron
1
from operator import truediv

c = truediv(a, b)

onde a é dividendo eb é o divisor. Esta função é útil quando quociente após a divisão de dois números inteiros é um ponto flutuante.

Chetan Yeshi
fonte