15

Jakiej klasy należy użyć do reprezentowania pieniędzy, aby uniknąć większości błędów zaokrąglania?Jaką klasę użyć do reprezentacji pieniędzy?

Czy powinienem używać Decimal, czy też prostego wbudowanego number?

Czy istnieje klasa Money z obsługą konwersji walut, z której mógłbym skorzystać?

Jakieś pułapki, których powinienem unikać?

+0

Zawsze uważałem, że przeliczanie walut jest po prostu mnożeniem. – SilentGhost

+2

@SilentGhost: Tak i nie. Musisz pamiętać, * jak * użyjesz wartości, które posiadasz. Jak to zrobić, gdy w zeszłym roku zapłaciłeś U $ S2000 + AR 6300 + 1500 USD, aw tym roku zapłaciłeś U4 S4000 + AR 1200 $ + 500 €?Jest wiele rzeczy, które musisz wziąć pod uwagę, więc obiekt 'Money' musiałby zapisać wartość historyczną * i * aktualną wartość. – voyager

+3

Pułapki, których należy unikać: używanie liczb zmiennoprzecinkowych. Zobacz przestrzeń biurową. –

Odpowiedz

6

Zakładam, że mówisz o Pythonie. http://code.google.com/p/python-money/ „prymitywów do pracy z pieniędzmi i walut w Pythonie” - tytuł jest wymowne :)

+1

Po to są tagi :) – voyager

+0

Patrząc na http://code.google.com/p/python-money/source/browse/trunk/money/Money.py, widzę, że używają one słowa "dziesiętny" dla reprezentacja wewnętrzna :) – voyager

4

Możesz być zainteresowany QuantLib za pracę z finansami.

Posiada wbudowane klasy obsługi typów walut i roszczeń 4 lata aktywnego rozwoju.

+0

Ten projekt wygląda interesująco, ale może być trochę za dużo, najprawdopodobniej do prostoty wykorzystam projekt czystego Pythona. – voyager

3

Możesz obejrzeć tę bibliotekę: python-money. Ponieważ nie mam z tym doświadczenia, nie mogę wypowiedzieć się na temat jego użyteczności.

A 'trik' można zatrudnić do obsługi waluty jako liczby całkowite:

  • pomnożyć przez 100/podzielić przez 100 (np $ 100,25 -> 10025), aby mieć reprezentację w 'centów'
+5

Wiele systemów księgowych śledzi sprawy znacznie dokładniej niż do centów. –

+0

To prawda, ale wszystko zależy od potrzeb, które myślę ... Biblioteka kwantowa, do której odnosi się ten wątek, wydaje się być dobrym kandydatem do "poważnej" pracy finansowej. – ChristopheD

8

Wystarczy użyć decimal.

+1

decimal nie jest odpowiedni ze względu na sposób, w jaki obsługuje precyzję. Załóżmy, że masz do czynienia z kwotami mniejszymi niż 10 miliardów dolarów z dokładnością 0,01 $, więc możesz powiedzieć bibliotece dziesiętnej, że twoje liczby nie będą miały więcej niż 12 cyfr. Teraz masz dwa problemy: twój kod nie radzi sobie z hiperinflacją; a 0,01 USD będzie wyświetlane jako "0.010000000000". – Pitarou

9

Nigdy nie używaj liczby zmiennoprzecinkowej do reprezentowania pieniędzy. Liczby zmiennoprzecinkowe nie przedstawiają dokładnie liczb w formacie dziesiętnym. Kończy się koszmarem złożonych błędów zaokrąglania i nie można wiarygodnie konwertować między walutami. Zobacz Martin Fowler's short essay on the subject.

Jeśli zdecydujesz się napisać własną klasę, polecam ją na podstawie typu danych decimal.

Nie sądzę, że pieniądze z Pythona są dobrym rozwiązaniem, ponieważ nie utrzymywały się przez dłuższy czas, a jego kod źródłowy zawiera dziwny i bezużyteczny kod, a wymiana walut jest po prostu zepsuta.

Wypróbuj py-moneyed. To ulepszenie w stosunku do pieniędzy Pythona.

0

Prosty, lekki, rozciągliwy jeszcze pomysł:

class Money(): 

    def __init__(self, value): 
     # internally use Decimal or cents as long 
     self._cents = long(0) 
     # Now parse 'value' as needed e.g. locale-specific user-entered string, cents, Money, etc. 
     # Decimal helps in conversion 

    def as_my_app_specific_protocol(self): 
     # some application-specific representation 

    def __str__(self): 
     # user-friendly form, locale specific if needed 

    # rich comparison and basic arithmetics 
    def __lt__(self, other): 
     return self._cents < Money(other)._cents 
    def __add__(self, other): 
     return Money(self._cents + Money(other)._cents) 

Można:

  • Wdrożenie tylko to, co jest potrzebne w danej aplikacji.
  • Rozszerz go, gdy będziesz rosnąć.
  • Zmień wewnętrzną reprezentację i implementację w razie potrzeby.