Ograniczenie unosi się do dwóch miejsc po przecinku

1692

Chcę azostać zaokrąglony do 13,95 .

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

Ta roundfunkcja nie działa w oczekiwany sposób.

ShadowRanger
źródło
6
Hmm ... Próbujesz reprezentować walutę? Jeśli tak, nie powinieneś używać liczb zmiennoprzecinkowych za dolary. Prawdopodobnie możesz użyć liczb zmiennoprzecinkowych do groszy lub jakiejkolwiek najmniejszej wspólnej jednostki waluty, którą próbujesz wymodelować, ale najlepszą praktyką jest stosowanie reprezentacji dziesiętnej, jak sugerował HUAGHAGUAH w swojej odpowiedzi.
SingleNegationElimination
63
Ważne jest, aby nie przedstawiać waluty w liczbach zmiennoprzecinkowych. Pływaki nie są precyzyjne. Ale kwoty w groszach lub centach są liczbami całkowitymi. Dlatego liczby całkowite są poprawnym sposobem reprezentowania waluty.
Davoud Taghawi-Nejad
2
@ DavoudTaghawi-Nejad lub więcej do rzeczy ... Typ dziesiętny
podstawowy
17
Przyjeżdżam tu chyba za późno, ale chciałem zapytać, czy twórcy Pythona rozwiązali ten problem? Ponieważ kiedy robię rundę (13.949999999999999, 2), po prostu dostaję 13,95. Próbowałem w Pythonie 2.7.6, a także 3.4. To działa. Nie jestem pewien, czy w 2009 roku w ogóle było 2.7. Może to coś w Pythonie 2.5?
bad_keypoints

Odpowiedzi:

1689

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,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

Jeśli szukasz tylko dwóch miejsc po przecinku (na przykład, aby wyświetlić wartość waluty), masz kilka lepszych możliwości:

  1. Użyj liczb całkowitych i przechowuj wartości w centach, a nie w dolarach, a następnie podziel przez 100, aby przeliczyć na dolary.
  2. Lub użyj stałej liczby punktowej, np . Dziesiętnej .
Rex Logan
źródło
27
@Christian Istnieje zasadnicza różnica między przechowywaną wartością a sposobem jej wyświetlania . Sformatowanie danych wyjściowych powinno umożliwić dodanie dopełnienia zgodnie z wymaganiami, a także dodanie separatorów przecinków itp.
Podstawowy
22
warto wspomnieć, "%.2f" % round(a,2)że możesz umieścić nie tylko w printf, ale także w takich rzeczach jakstr()
andilabs
20
dlaczego ludzie zawsze przyjmują walutę w zaokrąglaniu zmiennoprzecinkowym? czasami po prostu chcesz pracować z mniejszą precyzją.
worc
9
@radtek: Musisz zrozumieć, że wartość binarna (typu 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ę.
John Y
12
@radtek: Dosłownie poprosiłeś o wyjaśnienie. Najprostszym rozwiązaniem jest rzeczywiście zastosowanie 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.
John Y
586

Istnieją nowe specyfikacje formatu, mini-język specyfikacji formatu ciągu :

Możesz zrobić to samo co:

"{:.2f}".format(13.949999999999999)

Uwaga 1: powyższe zwraca ciąg znaków. Aby uzyskać pływak, po prostu owiń float(...):

float("{:.2f}".format(13.949999999999999))

Uwaga 2: zawijanie float()nic nie zmienia:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True
Xolve
źródło
17
aby dodać przecinki, możesz także '{0:,.2f}'.format(1333.949999999)wydrukować '1,333.95'.
Stephen Blum,
@ OnurYıldırım: tak, ale możesz to owinąć float(); float("{0:.2f}".format(13.9499999))
Jossef Harush
5
@JossefHarush możesz owinąć go float (), ale nic nie zyskałeś. Teraz znów masz pływak, z tą samą niedokładnością. 13.9499999999999 i 13.95 są tym samym pływakiem.
Ned Batchelder,
4
@NedBatchelder: Zgadzam się, że są równe, ale to ogranicza liczbę zmiennoprzecinkową do dwóch miejsc po przecinku :)
Jossef Harush
8
Nawiasem mówiąc, od Python 3.6 możemy używać f-stringów:f"Result is {result:.2f}"
Andrey Semakin
289

Wbudowany round() działa dobrze w Pythonie 2.7 lub nowszym.

Przykład:

>>> round(14.22222223, 2)
14.22

Sprawdź dokumentację .

Chribsen
źródło
1
Czy mam więc zrozumieć, że jest to błąd Python 2.7? Dlaczego tak fundamentalna funkcja miałaby dawać różne wyniki od wersji 2.7 do wersji 3?
MikeM
ale round(2.16, 1)podaj, 2.2dlaczego python oferuje po prostu truncatefunc
jiamo
Na przykład, jeśli spróbujesz zaokrąglić wartość 2.675 do dwóch miejsc po przecinku, otrzymasz ten >>> round(2.675, 2) 2.67 docs.python.org/2/tutorial/floatingpoint.html
niebezpieczeństwo89
4
Ze strony dokumentacji Python 3:Note 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.
Richard Dally
Zauważ, że jeśli spróbujesz użyć tej metody do wydrukowania liczby, takiej jak 1.00000, wydrukuje ona tylko 1,0, niezależnie od liczby podanych miejsc dziesiętnych.
Josh Correia,
142

Uważam, że najprostszym podejściem jest użycie format() funkcji.

Na przykład:

a = 13.949999999999999
format(a, '.2f')

13.95

Daje to liczbę zmiennoprzecinkową jako ciąg zaokrąglony do dwóch miejsc po przecinku.

Grant Żukowski
źródło
97

Posługiwać się

print"{:.2f}".format(a)

zamiast

print"{0:.2f}".format(a)

Ponieważ to ostatnie może prowadzić do błędów wyjściowych podczas próby wyprowadzenia wielu zmiennych (patrz komentarze).

Aleksiej Antonienko
źródło
2
To nonsens. Dwie podane instrukcje zachowują się identycznie w Pythonie 2.7, a tylko druga instrukcja jest poprawna w Pythonie 2.6. (Żadna z tych instrukcji nie jest poprawna w Pythonie 3 lub Pythonie <2.6.) Pierwsza forma nie ma przewagi poza zwięzłością.
Mark Dickinson
1
Mam na myśli wydrukowanie „{0: .2f} {0: .2f}”. Format (a, b) doprowadzi do błędu w danych wyjściowych - dwukrotnie wyśle ​​wartość „a”. Podczas drukowania „{:. 2f} {: .2f}”. Format (a, b) wyświetli wartości „a” i „b”.
Aleksiej Antonienko
2
W przypadku Python 3 wystarczy dodać nawiasy drukuj (...). A w nich wszystko, co napisałem, ma rację.
Aleksiej Antonienko
„Mam na myśli, wydrukuj„ {0: .2f} {0: .2f} ”. Format (a, b) doprowadzi do błędu w danych wyjściowych”. Ach To całkiem inne stwierdzenie! Może powinieneś edytować swoją odpowiedź? (Co na przykład oznacza „podniesienie błędu” w bieżącej odpowiedzi? Czy możesz podać przykład przypadku, w którym drugie stwierdzenie podnosi wyjątek, ale pierwsze nie?)
Mark Dickinson
3
Byłbyś po wydruku („{0: .2f} {1: .2f}”. Format (a, b)), jeśli masz dwie zmienne
Hovo
95

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

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

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
68

Wypróbuj poniższy kod:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99
ax003d
źródło
Ale uwaga, wartość a jest wciąż nieprecyzyjnym pływakiem. Spójrz tutaj - repl.it/LJs (kliknij „Uruchom sesję” w górnej części prawej sekcji).
lifebalance
3
Jeśli wybierzesz to podejście, dodaj 0,5, aby uzyskać dokładniejszą reprezentację. int (a * 100 + 0,5) / 100,0; Inną opcją jest użycie math.ceil.
arhuaco
3
@ShashankSawant: Cóż, po pierwsze, przedstawiona odpowiedź nie jest zaokrąglona, ​​ale zostaje obcięta. Sugestia dodania połowy na końcu zaokrągli się, ale wtedy nie ma żadnej korzyści z robienia tego więcej niż z samej roundfunkcji. Po drugie, ponieważ to rozwiązanie nadal wykorzystuje zmiennoprzecinkowy, pierwotny problem PO pozostaje, nawet w przypadku „poprawionej” wersji tego „rozwiązania”.
John Y,
3
-1, jest to po prostu niepotrzebna ponowna implementacja roundfunkcji (która została użyta w pytaniu).
interjay
4
@interjay, co jest konieczne, jeśli round()nie działa tak, jak wspomniany PO.
Pithikos,
57

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() ...lub Decimal -> 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 :

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

Dokumentacja

Zobacz informacje o wersji Python 2.7 - inny język Zmienia czwarty akapit:

Konwersje między liczbami zmiennoprzecinkowymi a łańcuchami są teraz poprawnie zaokrąglane na większości platform. Te konwersje zachodzą w wielu różnych miejscach: str () na liczbach zmiennoprzecinkowych i liczbach zespolonych; konstrukcje zmiennoprzecinkowe i złożone; formatowanie numeryczne; szeregowania i DE-szeregowania pływaków i liczbach zespolonych z wykorzystaniem marshal, picklei jsonmodułów; parsowanie pływaków i urojonych literałów w kodzie Pythona; oraz konwersja dziesiętna na zmiennoprzecinkową.

W związku z tym repr () liczby zmiennoprzecinkowej x zwraca teraz wynik oparty na najkrótszym ciągu dziesiętnym, który gwarantuje zaokrąglenie z powrotem do x przy prawidłowym zaokrągleniu (w trybie zaokrąglania od połowy do parzystej). Poprzednio dawał ciąg oparty na zaokrąglaniu x do 17 cyfr dziesiętnych.

Powiązany problem


Więcej informacji: Formatowanie floatprzed Pythonem 2.7 było podobne do bieżącego numpy.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 konwersja repr(float(number_as_string))nie jest odwracalna w przypadku numpy. Z drugiej strony:float.__repr__

hynekcer
źródło
Dlaczego głosowałeś za daleko? Pytanie dotyczyło Pythona float(podwójna precyzja) i normalnego round, 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.
hynekcer
53 bity, jeśli uwzględnisz „ukryty bit”, który jest domyślny 1, z wyjątkiem „stopniowego niedomiaru”.
Rick James
To nie jest wina rundy, to wina wyświetlacza.
Rick James
Tak, jest dobrze znany. Brakuje mi jednak kontekstu, jeśli sprzeciwisz się czemuś w uwagach do wydania Python 2.7 lub w moim tekście lub w ogóle nic. To pytanie jest bardziej skomplikowane niż było to konieczne. Należy dodać, że w Pythonie 2.7 poprawiono także konwersję ciągów znaków na zmiennoprzecinkowe ze względu na błąd zaokrąglania niektórych 32-bitowych układów Intel i że „funkcja round () jest teraz poprawnie zaokrąglona”. ( Informacje o wersji - funkcje 3.1 przeniesione do wersji 2.7 ). Czy możesz się zgodzić?
hynekcer
1
Ups, to było a*bkontra b*a. Dzięki za linki - Nostalgia.
Rick James
52

W przypadku języka Python <3 (np. 2.6 lub 2.7) można to zrobić na dwa sposoby.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

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

AJ
źródło
Jak reprezentujesz liczbę całkowitą? Jeśli użyję formatu „{i3}”. (Numvar), pojawia się błąd.
skytux,
To mam na myśli: jeśli numvar=12.456, to "{:.2f}".format(numvar)daje, 12.46ale "{:2i}".format(numvar)daje błąd i oczekuję 12.
skytux
50

Możesz zmodyfikować format wyjściowy:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95
Greg Hewgill
źródło
47

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:

>>> f'{a:.2f}'

Działa dobrze również z dłuższymi przykładami, z operatorami i nie potrzebującymi parens:

>>> print(f'Completed in {time.time() - start:.2f}s')
Matt Fletcher
źródło
39

Możesz użyć operatora formatu do zaokrąglenia wartości do 2 miejsc po przecinku w pythonie:

print(format(14.4499923, '.2f')) // output is 14.45
Asad Manzoor
źródło
4
Zwraca ciąg znaków
Jemshit Iskenderov
29

W Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output
Shashank Singh
źródło
1
To wcale nie pomaga. outputma dokładnie taką samą wartość jak a, więc równie dobrze możesz napisać print azamiast print outputw ostatnim wierszu.
Mark Dickinson
@MarkDickinson Czy możesz spróbować ponownie? Ponieważ działa w oczekiwany sposób w moim kompilatorze.
Shashank Singh,
1
Nie rozumiesz mnie. Tak, twój kod jest drukowany 13.95. Podobnie jest print aw przypadku tej konkretnej wartości aw Pythonie 2.7, więc nie jest do końca jasne, jaki był sens kroku formatowania.
Mark Dickinson
@MarkDickinson Edytowałem kod. Zgadzam się, że „print a” drukuje tę samą wartość, co „wydruk”. Ale jeśli porównasz wynik „a ==”, wynikiem będzie „False”, ponieważ krok formatowania zaokrągla zmienną wartość „a” do dwóch miejsc po przecinku.
Shashank Singh,
1
Czy rzeczywiście próbowałeś a == outputpokazać kod? Daje Truemi to i podejrzewam, że to także dla ciebie.
Mark Dickinson
22

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ę:

>>> 0.1
0.10000000000000001

możesz pokusić się o użycie tej round() funkcji, aby przyciąć ją z powrotem do oczekiwanej cyfry. Ale to nie robi różnicy:

>>> round(0.1, 1)
0.10000000000000001

Problem polega na tym, że przechowywana binarna wartość zmiennoprzecinkowa “0.1” była już najlepszym możliwym przybliżeniem binarnym 1/10, więc próba zaokrąglenia jej ponownie nie może poprawić: była już tak dobra, jak to możliwe.

Inną konsekwencją jest to, że ponieważ 0.1 nie jest dokładnie 1/10, sumowanie dziesięciu wartości 0.1może nie dać dokładnie 1.0:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

Jedną alternatywą i rozwiązaniem twoich problemów byłoby użycie decimalmodułu.

nosklo
źródło
18

Jak wskazał @Matt, Python 3.6 dostarcza ciągi f , a także może używać zagnieżdżonych parametrów :

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

który wyświetli się result: 2.35

toto_tico
źródło
11

Użyj kombinacji obiektu Decimal i metody round ().

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')
Jonathan L.
źródło
7

Używam tej techniki do ustalania liczb zmiennoprzecinkowych w językach dynamicznych typu, takich jak Python i JavaScript

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

Możesz także użyć Dziesiętnej w następujący sposób:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')
Siamand
źródło
1
getcontext().prec = 6działa tylko dla zakresu funkcji lub wszystkich miejsc?
Julio Marins
1
Konteksty to środowiska dla operacji arytmetycznych. Regulują precyzję, ustalają reguły zaokrąglania, określają, które sygnały są traktowane jako wyjątki i ograniczają zasięg wykładników. Każdy wątek ma swój bieżący kontekst @JulioMarins
Siamand
7
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Wyniki:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'
tkanie
źródło
6
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14,54

MikeL
źródło
5

Co z taką funkcją lambda:

arred = lambda x,n : x*(10**n)//1/(10**n)

W ten sposób możesz po prostu:

arred(3.141591657,2)

i dostać

3.14
Gustavo Mirapalheta
źródło
4

To proste jak 1,2,3:

  1. użyj dziesiętnego modułu do szybkiej poprawnie zaokrąglonej arytmetyki zmiennoprzecinkowej dziesiętnej:

    d = dziesiętny (10000000,0000009)

aby zaokrąglić:

   d.quantize(Decimal('0.01'))

spowoduje wyniki z Decimal('10000000.00')

  1. zrobić powyżej SUCHEGO:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

LUB

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. głosuj na tę odpowiedź :)

PS: krytyka innych: formatowanie nie jest zaokrąglone.

Sławomir Lenart
źródło
2

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

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0
iblasi
źródło
nie działa dla mnie w Pythonie 3.4.3 i Numpy 1.9.1? >>> importuj numpy jako np >>> res = 0,01 >>> wartość = 0,184 >>> np.round (wartość / res) * res 0,17999999999999999
szeitlin
1
Szukając dokumentacji widzę, że problem pochodzi z numpy.rounddokładności / precyzji. Wymaga więc zdefiniowania go jako int przed pomnożeniem przez rozdzielczość. Zaktualizowałem kod. Dziękuję za to!
iblasi
Konieczne jest jedynie przekonwertowanie numpy.float64wyniku np.round na floatlub po prostu użycie round(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.
hynekcer
@hynekcer Nie sądzę, że moja odpowiedź jest najlepsza. Chciałem tylko dodać przykład liczby zmiennoprzecinkowej do n miejsc po przecinku, ale najbliższy określonej rozdzielczości. Sprawdziłem, jak powiedziałeś, że zamiast intciebie możesz również użyć floatna przykład @szeitlin. Dziękujemy za dodatkowy komentarz. (Przepraszam, ale nie przegłosowałem)
iblasi,
Dodanie zupełnie nowej zależności do przetwarzania numerycznego (pandy) to „najlepszy sposób”?
Hejazzman
1

lambda x, n: int (x * 10 n + .5) / 10 n pracuje dla mnie od wielu lat w wielu językach.

Ray Tayek
źródło
-13

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.

float = str(float)[:5]

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!

tdh
źródło
2
Nie publikuj identycznych odpowiedzi na wiele pytań.
vaultah
18
WOW ... tdh ... Nigdy nie twórz żadnego oprogramowania księgowego ... Co się stanie, jeśli liczba będzie wynosić 113,94? skutkowałoby to 113,9 ... brakiem 0,04 .... To także ma już odpowiedzi sprzed ponad 5 lat ...
Angry 84