Converter um float em string sem arredondá-lo

88

Estou fazendo um programa que, por motivos que não precisam ser explicados, requer que um float seja convertido em uma string a ser contada com len (). No entanto, str (float (x)) resulta em x sendo arredondado quando convertido em uma string, o que joga tudo fora. Alguém sabe de uma solução para isso? Este é o código que está sendo usado se você quiser saber:

len(str(float(x)/3))
Galileo
fonte
2
se x é originalmente str, por que o elenco?
Vinko Vrsalovic
1
-1: Sem exemplos, a saída necessária para diferentes valores de x. Sem exemplos, podemos apenas adivinhar qual é o problema.
S.Lott

Respostas:

129

Algumas formas de arredondamento costumam ser inevitáveis ​​ao lidar com números de ponto flutuante. Isso ocorre porque os números que você pode expressar exatamente na base 10 nem sempre podem ser expressos exatamente na base 2 (que o seu computador usa).

Por exemplo:

>>> .1
0.10000000000000001

Neste caso, você está vendo .1 convertido em uma string usando repr:

>>> repr(.1)
'0.10000000000000001'

Eu acredito que o python corta os últimos dígitos quando você usa str () para contornar este problema, mas é uma solução alternativa parcial que não substitui a compreensão do que está acontecendo.

>>> str(.1)
'0.1'

Não tenho certeza de quais problemas o "arredondamento" está causando. Talvez você se saísse melhor com a formatação de strings como uma forma de controlar mais precisamente sua saída?

por exemplo

>>> '%.5f' % .1
'0.10000'
>>> '%.5f' % .12345678
'0.12346'

Documentação aqui .

John Fouhy
fonte
12
len(repr(float(x)/3))

No entanto, devo dizer que isso não é tão confiável quanto você pensa.

Floats são inseridos / exibidos como números decimais, mas seu computador (na verdade, sua biblioteca C padrão) os armazena como binários. Você obtém alguns efeitos colaterais dessa transição:

>>> print len(repr(0.1))
19
>>> print repr(0.1)
0.10000000000000001

A explicação de por que isso acontece está neste capítulo do tutorial de python.

Uma solução seria usar um tipo que rastreia especificamente números decimais, como o de python decimal.Decimal:

>>> print len(str(decimal.Decimal('0.1')))
3
nosklo
fonte
Boa postagem sobre como trabalhar com resultados de flutuação da divisão: stackoverflow.com/questions/2958684/python-division
Trutane 01 de
3

Outras respostas já apontaram que a representação de números flutuantes é uma questão espinhosa, para dizer o mínimo.

Como você não fornece contexto suficiente para sua pergunta, não posso saber se o módulo decimal pode ser útil para suas necessidades:

http://docs.python.org/library/decimal.html

Entre outras coisas, você pode especificar explicitamente a precisão que deseja obter (nos documentos):

>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')

Um exemplo simples do meu prompt (python 2.6):

>>> import decimal
>>> a = decimal.Decimal('10.000000001')
>>> a
Decimal('10.000000001')
>>> print a
10.000000001
>>> b = decimal.Decimal('10.00000000000000000000000000900000002')
>>> print b
10.00000000000000000000000000900000002
>>> print str(b)
10.00000000000000000000000000900000002
>>> len(str(b/decimal.Decimal('3.0')))
29

Talvez isso possa ajudar? decimal está em python stdlib desde 2.4, com adições em python 2.6.

Espero que isso ajude, Francesco

Francesco
fonte
0

Sei que é tarde demais, mas para quem está vindo pela primeira vez, gostaria de postar uma solução. Eu tenho um valor flutuante indexe uma string imgfilee tive o mesmo problema que você. Foi assim que resolvi o problema

index = 1.0
imgfile = 'data/2.jpg'
out = '%.1f,%s' % (index,imgfile)
print out

A saída é

1.0,data/2.jpg

Você pode modificar este exemplo de formatação conforme sua conveniência.

Harsh Wardhan
fonte