Tworzę program, który z powodów, których nie trzeba wyjaśniać, wymaga konwersji typu float na ciąg znaków do policzenia za pomocą len (). Jednak str (float (x)) powoduje, że x jest zaokrąglane po konwersji na łańcuch, co odrzuca całość. Czy ktoś wie, jak to naprawić? Oto kod używany, jeśli chcesz wiedzieć:
len(str(float(x)/3))
python
string
floating-point
rounding
Galileo
źródło
źródło
x
. Bez przykładów możemy tylko zgadywać, na czym polega problem.Odpowiedzi:
W przypadku liczb zmiennoprzecinkowych często nie można uniknąć pewnych form zaokrąglania. Dzieje się tak, ponieważ liczby, które możesz wyrazić dokładnie w podstawie 10, nie zawsze mogą być wyrażone dokładnie w podstawie 2 (której używa twój komputer).
Na przykład:
>>> .1 0.10000000000000001
W tym przypadku widzisz .1 przekonwertowane na ciąg przy użyciu
repr
:>>> repr(.1) '0.10000000000000001'
Uważam, że Python odcina kilka ostatnich cyfr, gdy używasz str (), aby obejść ten problem, ale jest to częściowe obejście, które nie zastępuje zrozumienia, co się dzieje.
>>> str(.1) '0.1'
Nie jestem pewien, jakie problemy powodują „zaokrąglanie”. Być może lepiej by było, gdyby formatowanie napisów było sposobem na dokładniejszą kontrolę wyników?
na przykład
>>> '%.5f' % .1 '0.10000' >>> '%.5f' % .12345678 '0.12346'
Dokumentacja tutaj .
źródło
len(repr(float(x)/3))
Muszę jednak powiedzieć, że nie jest to tak wiarygodne, jak myślisz.
Liczba zmiennoprzecinkowa jest wprowadzana / wyświetlana jako liczby dziesiętne, ale Twój komputer (w rzeczywistości Twoja standardowa biblioteka C) przechowuje je jako binarne. To przejście daje pewne efekty uboczne:
>>> print len(repr(0.1)) 19 >>> print repr(0.1) 0.10000000000000001
Wyjaśnienie, dlaczego tak się dzieje, znajduje się w tym rozdziale samouczka Pythona.
Rozwiązaniem byłoby użycie typu, który specjalnie śledzi liczby dziesiętne, na przykład w języku Python
decimal.Decimal
:>>> print len(str(decimal.Decimal('0.1'))) 3
źródło
Inne odpowiedzi już wskazywały, że reprezentacja liczb zmiennoprzecinkowych jest co najmniej drażliwą kwestią.
Ponieważ nie podajesz wystarczającego kontekstu w swoim pytaniu, nie mogę wiedzieć, czy moduł dziesiętny może być przydatny dla Twoich potrzeb:
http://docs.python.org/library/decimal.html
Między innymi możesz wyraźnie określić dokładność, którą chcesz uzyskać (z 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 znaku zachęty (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? decimal jest w pythonie stdlib od 2.4, z dodatkami w pythonie 2.6.
Mam nadzieję, że to pomoże, Francesco
źródło
Wiem, że jest już za późno, ale dla tych, którzy przyjeżdżają tu po raz pierwszy, chciałbym zamieścić rozwiązanie. Mam wartość zmiennoprzecinkową
index
i ciąg znakówimgfile
i miałem ten sam problem co Ty. W ten sposób rozwiązałem problemindex = 1.0 imgfile = 'data/2.jpg' out = '%.1f,%s' % (index,imgfile) print out
Wynik jest
1.0,data/2.jpg
Możesz zmodyfikować ten przykład formatowania według własnego uznania.
źródło