2009-08-23 14 views
60

Tworzę program, który z powodów, które nie wymagają wyjaśnienia, wymaga przekonwertowania elementu pływającego na ciąg znaków, który będzie liczony za pomocą len(). Jednakże, str (float (x)) powoduje, że x jest zaokrąglane po przekonwertowaniu na ciąg, który wyrzuca całą rzecz. Czy ktoś wie o poprawce? Oto kod używany, jeśli chcesz wiedzieć:Konwertowanie zmiennoprzecinkowej na ciąg bez zaokrąglania go

len(str(float(x)/3)) 
+2

jeśli x jest oryginalnie str, dlaczego obsada? –

+1

-1: Brak przykładów wymaganych danych wyjściowych dla różnych wartości 'x'. Bez przykładów możemy tylko zgadywać, na czym polega problem. –

Odpowiedz

92

Niektóre formy zaokrąglenia jest często nieuniknione, gdy ma do czynienia z liczb zmiennoprzecinkowych. Dzieje się tak dlatego, że liczby, które można wyrazić dokładnie w bazie 10, nie zawsze mogą być wyrażone dokładnie w bazie 2 (używanej przez komputer).

Na przykład:

>>> .1 
0.10000000000000001 

W tym przypadku, widzisz .1 konwertowane do łańcucha za pomocą repr:

>>> repr(.1) 
'0.10000000000000001' 

wierzę kotlety Pythona off ostatnich kilku cyfr podczas korzystania str() w celu obejścia tego problemu, ale jest to częściowe obejście, które nie zastępuje zrozumienia tego, co się dzieje.

>>> str(.1) 
'0.1' 

Nie jestem do końca pewien, jakie problemy powoduje "zaokrąglanie". Być może lepiej by było, gdyby formatowanie ciągów było sposobem na dokładniejszą kontrolę nad wydrukiem?

np.

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

Documentation here.

10
len(repr(float(x)/3)) 

Jednak muszę powiedzieć, że to nie jest tak wiarygodne, jak myślisz.

Pływaki są wprowadzane/wyświetlane jako liczby dziesiętne, ale komputer (w rzeczywistości, standardowa biblioteka C) przechowuje je jako pliki binarne. Masz jakieś skutki uboczne z tego przejścia:

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

Wyjaśnienie dlaczego tak się dzieje jest w this chapter samouczka Pythona.

Rozwiązaniem byłoby użyć typu, które specyficznie śledzi liczby dziesiętne, jak Pythona decimal.Decimal:

>>> print len(str(decimal.Decimal('0.1'))) 
3 
+3

+1 dla dziesiętnych. –

+0

Dobry post dotyczący sposobu pracy z floatem wynika z podziału: https://stackoverflow.com/questions/2958684/python-division – Trutane

3

Inne odpowiedzi wskazywały już, że reprezentacja liczb zmiennoprzecinkowych jest co najmniej drażliwa.

Ponieważ nie dają wystarczającej kontekst w swoim pytaniu, nie mogę wiedzieć, czy moduł dziesiętne mogą być przydatne dla Twoich potrzeb:

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

Wśród innych rzeczy, które można jednoznacznie określić precyzję że cię chcą uzyskać (od dokumentów):

>>> 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') 

Prosty przykład z mojego pytania (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 

Może to może pomóc? dziesiętny jest w python stdlib od 2,4, z dodatkami w python 2.6.

Nadzieja to pomaga, Francesco

Powiązane problemy