2011-12-21 11 views
16

wymowne, chcę dostać 1324343032.324Przybliżenie do 3 miejsc po przecinku w Pythonie

Jak widać poniżej, następujące nie działają:

>>1324343032.324325235 * 1000/1000 
1324343032.3243253 
>>int(1324343032.324325235 * 1000)/1000.0 
1324343032.3239999 
>>round(int(1324343032.324325235 * 1000)/1000.0,3) 
1324343032.3239999 
>>str(1324343032.3239999) 
'1324343032.32' 
+4

Nie ma takiej wartości w zestawie, które są reprezentowane przez liczb zmiennoprzecinkowych. –

+2

Na wypadek, gdyby komentarz Karla nie był wystarczająco wyraźny: * Nie ma * takiej liczby * jak 1324343032.324 w binarnym zmiennoprzecinkowym. Jeśli zmienisz wersję Pythona na wyższą (2.7 lub 3.1 lub nowsza), interpreter * wyświetli * 1324343032.324 dla ciebie. Ale w rzeczywistości liczba, z którą się liczysz, nie jest ani 1324343032.324, ani 1324343032.3239999 niezależnie od wersji Pythona. Jedynym sposobem uzyskania * dokładnie * 1324343032.324 jest użycie modułu 'decimal' lub jakiejś innej arbitralnej, precyzyjnej biblioteki matematycznej, takiej jak' gmpy'. –

+0

Przyjęta poniżej odpowiedź jest poprawna, jeśli chcesz zaokrąglić (w górę) do określonej liczby miejsc dziesiętnych. Jednak pytanie, które zadaje, i to, co chciałem wiedzieć, to sposób obcięcia do określonej liczby miejsc dziesiętnych. Dla mnie '% .3f '% (1324343032.3243)' i ''% .3f '% (1324343032.3245) dają różne wyniki. (Używam Pythona 2.7.8). – nullstellensatz

Odpowiedz

31

'%.3f'%(1324343032.324325235)

użyć dodatkowego float() wokół jeśli chcesz zachować go jako pływak.

+0

Nie chcę go wydrukować ... Chcę go zapisać – SuperString

+2

To jest właściwie poprawna odpowiedź, po prostu użyj 'val = '% .3f'% (1324343032.324325235)' zamiast 'print'. –

+0

Edytowane. Możesz go wydrukować, zapisać, cokolwiek. –

7

Jak o tym:

In [1]: '%.3f' % round(1324343032.324325235 * 1000/1000,3) 
Out[1]: '1324343032.324' 

Możliwy duplikat round() in Python doesn't seem to be rounding properly

[EDIT]

Biorąc pod uwagę dodatkowe komentarze Wierzę, że chcesz zrobić:

In : Decimal('%.3f' % (1324343032.324325235 * 1000/1000)) 
Out: Decimal('1324343032.324') 

The floa punkt dokładność ie nie będzie to, co chcesz:

In : 3.324 
Out: 3.3239999999999998 

(wszystkie przykłady są z Python 2.6.5)

3

Link Almo wyjaśnia dlaczego tak się dzieje. Aby rozwiązać problem, użyj decimal library.

6

Użyj modułu dziesiętnego. Ale jeśli musisz używać pływaków i nadal jakoś przymuszać je do określonej liczby miejsc po przecinku, konwersja na sznurki z tyłu zapewnia (raczej niezgrabną, boję się) metodę robienia tego.

>>> q = 1324343032.324325235 * 1000/1000 
>>> a = "%.3f" % q 
>>> a 
'1324343032.324' 
>>> b = float(a) 
>>> b 
1324343032.324 

Więc:

float("%3.f" % q) 
+1

Dobrze, że najpierw wspomniano o module dziesiętnym, ponieważ jest to jedyna w pełni poprawna odpowiedź. Jedną rzeczą, którą należy zachować z resztą, jest to, że 'b' w twoim przykładzie będzie wyświetlany jako 1324343032.3239999 w wersjach Pythona przed 2.7. I rzeczywiście, jest to wartość, którą OP widzi, kiedy próbuje. Oczywiście obie wartości są nie do odróżnienia pod względem binarnego zmiennoprzecinkowego. –

3

można użyć następujących funkcji obciąć liczbę do określonej liczby miejsc po przecinku:

import math 
def truncate(number, digits) -> float: 
    stepper = pow(10.0, digits) 
    return math.trunc(stepper * number)/stepper 

Zastosowanie:

>> truncate(1324343032.324325235, 3) 
>> 1324343032.324 
+1

To naprawdę powinna być zaakceptowana odpowiedź. Kod jest prosty, elegancki i ma największy sens. Użyj standardowej funkcji przycinania, jednak najpierw przesuń miejsce dziesiętne, przesuwając dziesiętne miejsce z powrotem po wykonaniu obcięcia. – CatalystNZ

5

I znalazłem inne rozwiązanie (musi być bardziej eff icient niż "string czary" obejścia):

>>> import decimal 
# By default rounding setting in python is decimal.ROUND_HALF_EVEN 
>>> decimal.getcontext().rounding = decimal.ROUND_DOWN 
>>> c = decimal.Decimal(34.1499123) 
# By default it should return 34.15 due to '99' after '34.14' 
>>> round(c,2) 
Decimal('34.14') 
>>> float(round(c,2)) 
34.14 
>>> print(round(c,2)) 
34.14 

About decimals module

About rounding settings

-1
>>> float(1324343032.324325235) * float(1000)/float(1000) 

1324343032.3243253 

>>> round(float(1324343032.324325235) * float(1000)/float(1000), 3) 

1324343032.324 
+1

Ten fragment kodu może rozwiązać pytanie, [w tym wyjaśnienie] (http: //meta.stackexchange.com/questions/114762/explanining-fully-code-based-answers) naprawdę pomaga poprawić jakość twojego posta. Pamiętaj, że odpowiadasz na pytanie przeznaczone dla czytelników w przyszłości, a te osoby mogą nie znać powodów sugestii dotyczących kodu. – DimaSan

-1

można również użyć:

import math 

nValeur = format(float(input('Quelle valeur ? ')), '.3f') 

W Pythonie 3.6 będzie działać

0

Po znalezieniu sposobu rozwiązania tego problemu, bez ładowania jakiegokolwiek modułu Python 3 lub dodatkowych operacji matematycznych, rozwiązałem problem, używając tylko funkcji str.format() e. Float().Myślę, że ten sposób jest szybszy niż w przypadku innych operacji matematycznych, jak w przypadku najbardziej popularnego rozwiązania. Potrzebowałem szybkiego rozwiązania, ponieważ pracuję z bardzo dużym zbiorem danych i dlatego działa on bardzo dobrze tutaj.

def truncate_number(f_number, n_decimals): 
     strFormNum = "{0:." + str(n_decimals+5) + "f}" 
     trunc_num = float(strFormNum.format(f_number)[:-5]) 
     return(trunc_num) 

# Testing the 'trunc_num()' function 
test_num = 1150/252 
[(idx, truncate_number(test_num, idx)) for idx in range(0, 20)] 

Zwraca następujący wynik:

[(0, 4.0), 
(1, 4.5), 
(2, 4.56), 
(3, 4.563), 
(4, 4.5634), 
(5, 4.56349), 
(6, 4.563492), 
(7, 4.563492), 
(8, 4.56349206), 
(9, 4.563492063), 
(10, 4.5634920634), 
(11, 4.56349206349), 
(12, 4.563492063492), 
(13, 4.563492063492), 
(14, 4.56349206349206), 
(15, 4.563492063492063), 
(16, 4.563492063492063), 
(17, 4.563492063492063), 
(18, 4.563492063492063), 
(19, 4.563492063492063)] 
1

wierzę przy użyciu funkcji formatowania jest złym pomysłem. Zobacz poniżej. Zaokrągla wartość. Używam Python3.6.

>>> '%.3f'%(1.9999999) 
'2.000' 

Użyj regex zamiast:

>>> re.match(r'\d+.\d{3}', str(1.999999)).group(0) 
'1.999' 
Powiązane problemy