Chcę a
zostać zaokrąglony do 13,95 .
>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999
Ta round
funkcja nie działa w oczekiwany sposób.
python
floating-point
rounding
precision
ShadowRanger
źródło
źródło
Odpowiedzi:
Napotykasz stary problem z liczbami zmiennoprzecinkowymi, że nie wszystkie liczby mogą być dokładnie reprezentowane. Wiersz poleceń pokazuje tylko pełną postać zmiennoprzecinkową z pamięci.
W przypadku reprezentacji zmiennoprzecinkowej zaokrąglona wersja ma ten sam numer. Ponieważ komputery są binarne, przechowują liczby zmiennoprzecinkowe jako liczby całkowite, a następnie dzielą je przez potęgę dwóch, więc 13,95 będzie reprezentowane w podobny sposób jak 125650429603636838 / (2 ** 53).
Liczby o podwójnej precyzji mają 53 bity (16 cyfr) precyzji, a zwykłe zmiennoprzecinkowe mają 24 bity (8 cyfr) precyzji. Typ zmiennoprzecinkowy w Pythonie używa podwójnej precyzji do przechowywania wartości.
Na przykład,
Jeśli szukasz tylko dwóch miejsc po przecinku (na przykład, aby wyświetlić wartość waluty), masz kilka lepszych możliwości:
źródło
"%.2f" % round(a,2)
że możesz umieścić nie tylko w printf, ale także w takich rzeczach jakstr()
float
) jest po prostu najbliższym dostępnym przybliżeniem liczby dziesiętnej (którą znasz jako człowiek). Nie ma takiej (finalnie reprezentowalnej) wartości binarnej jak 0.245. Po prostu nie istnieje i matematycznie nie może istnieć. Wartość binarna, która jest najbliższa 0,245, jest nieco mniejsza niż 0,245, więc naturalnie zaokrągla w dół. Podobnie, nie ma czegoś takiego jak 0.225 w binarnie, ale wartość binarna najbliższa 0,225 jest nieco większa niż 0,225, więc naturalnie zaokrągla się w górę.Decimal
, i było to jedno z rozwiązań przedstawionych w tej odpowiedzi. Drugim było przekonwertowanie ilości na liczby całkowite i użycie arytmetyki liczb całkowitych. Oba te podejścia pojawiły się również w innych odpowiedziach i komentarzach.Istnieją nowe specyfikacje formatu, mini-język specyfikacji formatu ciągu :
Możesz zrobić to samo co:
Uwaga 1: powyższe zwraca ciąg znaków. Aby uzyskać pływak, po prostu owiń
float(...)
:Uwaga 2: zawijanie
float()
nic nie zmienia:źródło
'{0:,.2f}'.format(1333.949999999)
wydrukować'1,333.95'
.float()
;float("{0:.2f}".format(13.9499999))
f"Result is {result:.2f}"
Wbudowany
round()
działa dobrze w Pythonie 2.7 lub nowszym.Przykład:
Sprawdź dokumentację .
źródło
round(2.16, 1)
podaj,2.2
dlaczego python oferuje po prostutruncate
func>>> round(2.675, 2) 2.67
docs.python.org/2/tutorial/floatingpoint.htmlNote The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Uważam, że najprostszym podejściem jest użycie
format()
funkcji.Na przykład:
Daje to liczbę zmiennoprzecinkową jako ciąg zaokrąglony do dwóch miejsc po przecinku.
źródło
Posługiwać się
zamiast
Ponieważ to ostatnie może prowadzić do błędów wyjściowych podczas próby wyprowadzenia wielu zmiennych (patrz komentarze).
źródło
Większość liczb nie może być dokładnie przedstawiona w liczbach zmiennoprzecinkowych. Jeśli chcesz zaokrąglić liczbę, ponieważ tego właśnie wymaga twoja formuła matematyczna lub algorytm, to chcesz użyć rundy. Jeśli chcesz ograniczyć wyświetlanie do określonej precyzji, nie używaj nawet okrągłego formatu i po prostu sformatuj go jako ten ciąg. (Jeśli chcesz wyświetlić go za pomocą alternatywnej metody zaokrąglania, a istnieją tony, musisz połączyć oba podejścia.)
I wreszcie, choć być może najważniejsze, jeśli chcesz dokładnej matematyki, to wcale nie chcesz pływaków. Typowym przykładem jest zajmowanie się pieniędzmi i przechowywanie „centów” jako liczby całkowitej.
źródło
Wypróbuj poniższy kod:
źródło
round
funkcji. Po drugie, ponieważ to rozwiązanie nadal wykorzystuje zmiennoprzecinkowy, pierwotny problem PO pozostaje, nawet w przypadku „poprawionej” wersji tego „rozwiązania”.round
funkcji (która została użyta w pytaniu).round()
nie działa tak, jak wspomniany PO.TLDR;)
Problem zaokrąglania wejścia / wyjścia został definitywnie rozwiązany w Pythonie 2.7.0 i 3.1 .
Prawidłowo zaokrągloną liczbę można odwrócić do przodu i do tyłu:
str -> float() -> repr() -> float() ...
lubDecimal -> float -> str -> Decimal
Typ dziesiętny nie jest już potrzebny do przechowywania.
(Oczywiście może być konieczne zaokrąglenie wyniku dodawania lub odejmowania zaokrąglonych liczb w celu wyeliminowania nagromadzonych błędów ostatniego bitu. Wyraźna arytmetyka dziesiętna może być nadal przydatna, ale konwersja na ciąg znaków o
str()
(tzn. Z zaokrągleniem do 12 prawidłowych cyfr ) jest zwykle wystarczająca, jeśli nie jest wymagana ekstremalna dokładność lub ekstremalna liczba kolejnych operacji arytmetycznych).Test nieskończony :
Dokumentacja
Zobacz informacje o wersji Python 2.7 - inny język Zmienia czwarty akapit:
Powiązany problem
Więcej informacji: Formatowanie
float
przed Pythonem 2.7 było podobne do bieżącegonumpy.float64
. Oba typy używają tej samej 64-bitowej podwójnej precyzji IEEE 754 z 52-bitową mantysą. Dużą różnicą jest to, że jest sformatowana tak, że każda cyfra jest ważna; sekwencja jest bez przerw, a konwersja jest odwracalna. Po prostu: jeśli być może masz numer numpy.float64, przekonwertuj go na zwykły zmiennoprzecinkowy, aby sformatować go dla ludzi, a nie dla procesorów numerycznych, w przeciwnym razie nic więcej nie jest potrzebne w Pythonie 2.7+.np.float64.__repr__
jest często formatowany z nadmierną liczbą dziesiętną, aby żaden bit nie mógł zostać utracony, ale nie istnieje poprawna liczba IEEE 754 między 13,94999999999999999 a 13,950000000000001. Wynik nie jest przyjemny, a konwersjarepr(float(number_as_string))
nie jest odwracalna w przypadku numpy. Z drugiej strony:float.__repr__
źródło
float
(podwójna precyzja) i normalnegoround
, a nie numpy.double i jego konwersji na ciąg. Zwykłe zaokrąglanie w Pythonie naprawdę nie może być wykonane lepiej niż w Pythonie 2.7. Większość odpowiedzi została napisana przed wersją 2.7, ale są one przestarzałe, choć początkowo były bardzo dobre. To jest powód mojej odpowiedzi.1
, z wyjątkiem „stopniowego niedomiaru”.a*b
kontrab*a
. Dzięki za linki - Nostalgia.W przypadku języka Python <3 (np. 2.6 lub 2.7) można to zrobić na dwa sposoby.
Ale zauważ, że dla wersji Pythona powyżej 3 (np. 3.2 lub 3.3) preferowana jest opcja druga .
Aby uzyskać więcej informacji na temat opcji drugiej, sugeruję ten link na temat formatowania ciągów z dokumentacji Pythona .
Aby uzyskać więcej informacji na temat opcji pierwszej, ten link wystarczy i zawiera informacje na temat różnych flag .
Odniesienie: Konwertuj liczbę zmiennoprzecinkową na określoną dokładność, a następnie skopiuj do ciągu
źródło
numvar=12.456
, to"{:.2f}".format(numvar)
daje,12.46
ale"{:2i}".format(numvar)
daje błąd i oczekuję12
.Możesz zmodyfikować format wyjściowy:
źródło
Wydaje się, że nikt tutaj jeszcze o tym nie wspominał, więc pozwólcie, że podam przykład w formacie f-string / template-string w Pythonie 3.6, który moim zdaniem jest pięknie schludny:
Działa dobrze również z dłuższymi przykładami, z operatorami i nie potrzebującymi parens:
źródło
Możesz użyć operatora formatu do zaokrąglenia wartości do 2 miejsc po przecinku w pythonie:
źródło
W Python 2.7:
źródło
output
ma dokładnie taką samą wartość jaka
, więc równie dobrze możesz napisaćprint a
zamiastprint output
w ostatnim wierszu.13.95
. Podobnie jestprint a
w przypadku tej konkretnej wartościa
w Pythonie 2.7, więc nie jest do końca jasne, jaki był sens kroku formatowania.a == output
pokazać kod? DajeTrue
mi to i podejrzewam, że to także dla ciebie.Samouczek języka Python zawiera dodatek o nazwie Arytmetyka zmiennoprzecinkowa: problemy i ograniczenia . Przeczytaj to. Wyjaśnia, co się dzieje i dlaczego Python robi wszystko, co w jego mocy. Ma nawet przykład, który pasuje do twojego. Pozwól, że zacytuję trochę:
Jedną alternatywą i rozwiązaniem twoich problemów byłoby użycie
decimal
modułu.źródło
Jak wskazał @Matt, Python 3.6 dostarcza ciągi f , a także może używać zagnieżdżonych parametrów :
który wyświetli się
result: 2.35
źródło
Robi dokładnie to, co mu kazałeś i działa poprawnie. Przeczytaj więcej o pomyleniu zmiennoprzecinkowym i spróbuj zamiast tego obiektów dziesiętnych .
źródło
Użyj kombinacji obiektu Decimal i metody round ().
źródło
Używam tej techniki do ustalania liczb zmiennoprzecinkowych w językach dynamicznych typu, takich jak Python i JavaScript
Możesz także użyć Dziesiętnej w następujący sposób:
źródło
getcontext().prec = 6
działa tylko dla zakresu funkcji lub wszystkich miejsc?Wyniki:
źródło
źródło
Co z taką funkcją lambda:
W ten sposób możesz po prostu:
i dostać
źródło
To proste jak 1,2,3:
użyj dziesiętnego modułu do szybkiej poprawnie zaokrąglonej arytmetyki zmiennoprzecinkowej dziesiętnej:
d = dziesiętny (10000000,0000009)
aby zaokrąglić:
spowoduje wyniki z
Decimal('10000000.00')
LUB
PS: krytyka innych: formatowanie nie jest zaokrąglone.
źródło
Aby zaokrąglić liczbę do rozdzielczości, najlepszym sposobem jest następujący sposób, który może działać z dowolną rozdzielczością (0,01 dla dwóch miejsc po przecinku lub nawet innych kroków):
źródło
numpy.round
dokładności / precyzji. Wymaga więc zdefiniowania go jako int przed pomnożeniem przez rozdzielczość. Zaktualizowałem kod. Dziękuję za to!numpy.float64
wyniku np.round nafloat
lub po prostu użycieround(value, 2)
. Nie istnieje prawidłowy numer IEEE 754 między 13,949999999999999 (= 1395 / 100.) a 3.950000000000001 (= 1395 * .01). Dlaczego uważasz, że twoja metoda jest najlepsza? Oryginalna wartość 13,949999999999999289 (= wartość = zaokrąglona (wartość, 2)) jest jeszcze bardziej dokładna niż twoja 13,95000000000000178 (wydrukowana przez np.float96). Więcej informacji na temat numpy jest teraz dodanych do mojej odpowiedzi , którą prawdopodobnie przypadkowo przegłosowałeś. Pierwotnie nie chodziło o numpy.int
ciebie możesz również użyćfloat
na przykład @szeitlin. Dziękujemy za dodatkowy komentarz. (Przepraszam, ale nie przegłosowałem)lambda x, n: int (x * 10 n + .5) / 10 n pracuje dla mnie od wielu lat w wielu językach.
źródło
Metodą, której używam, jest cięcie strun. Jest to stosunkowo szybkie i proste.
Najpierw przekonwertuj liczbę zmiennoprzecinkową na ciąg, wybierz długość, jaką chcesz.
W powyższym pojedynczym wierszu przekonwertowaliśmy wartość na ciąg znaków, a następnie zachowaliśmy ciąg tylko pierwszych czterech cyfr lub znaków (włącznie).
Mam nadzieję, że to pomaga!
źródło