Jaki jest najlepszy typ danych do wykorzystania pieniędzy w C #?
using System.ComponentModel.DataAnnotations;
[DataType(DataType.Currency)]
Jaki jest najlepszy typ danych do wykorzystania pieniędzy w C #?
using System.ComponentModel.DataAnnotations;
[DataType(DataType.Currency)]
Odpowiedzi:
Jak opisano dziesiętnie jako:
Słowo dziesiętne wskazuje 128-bitowy typ danych. W porównaniu do typów zmiennoprzecinkowych, typ dziesiętny ma większą dokładność i mniejszy zakres, co czyni go odpowiednim do obliczeń finansowych i pieniężnych .
Możesz użyć dziesiętnej w następujący sposób:
decimal myMoney = 300.5m;
Typ wartości dziesiętnej reprezentuje liczby dziesiętne w zakresie od dodatnich 79 228,162,514,264,337,593,543,950,335 do ujemnych 79 228,162,514,264,335,593. Typ wartości dziesiętnej jest odpowiedni do obliczeń finansowych wymagających dużej liczby znaczących cyfr całkowitych i ułamkowych i bez błędów zaokrąglania. Typ dziesiętny nie eliminuje potrzeby zaokrąglania. Raczej minimalizuje błędy wynikające z zaokrąglania.
Chciałbym wskazać na tę doskonałą odpowiedź , zastanawiając się, dlaczego podwójnego nie należy używać.
Użyj wzorca Money z wzorców architektury aplikacji korporacyjnych ; podaj kwotę jako dziesiętną, a walutę jako wyliczenie.
Money
nuget ma martwy link do strony projektu, więc ... żadnych dokumentów?
Dziesiętny. Jeśli wybierzesz podwójnie, narażasz się na błędy zaokrąglania
double
może wprowadzać błędy zaokrąglania, ponieważ zmiennoprzecinkowe nie mogą dokładnie reprezentować wszystkich liczb (np. 0,01 nie ma dokładnej reprezentacji w liczbach zmiennoprzecinkowych). Decimal
Z drugiej strony, nie stanowią numery dokładnie . (Kompromis Decimal
ma mniejszy zakres niż zmiennoprzecinkowy) Zmienny punkt może dać * niezamierzone * błędy zaokrąglania (np 0.01+0.01 != 0.02
.). Decimal
może dać ci błędy zaokrąglania, ale tylko wtedy, gdy o to poprosisz (np. Math.Round(0.01+0.02)
zwraca zero)
double
i ostrożnie stosuje skalowanie i zaokrąglanie specyficzne dla dziedziny, w stosownych przypadkach, może to być całkowicie precyzyjne. Jeśli ktoś jest niechlujny w swoim zaokrąglaniu, decimal
może dać wyniki, które są semantycznie niepoprawne (np. Jeśli doda się wiele wartości, które powinny być zaokrąglone do najbliższego grosza, ale tak naprawdę nie wokół nich w pierwszej kolejności). Jedyną dobrą rzeczą decimal
jest to, że skalowanie jest wbudowane.
dziesiętny ma mniejszy zakres, ale większą precyzję - dzięki czemu nie tracisz z czasem wszystkich tych groszy!
Pełne szczegóły tutaj:
Zgadzam się z wzorem Pieniądza: Posługiwanie się walutami jest po prostu zbyt uciążliwe, gdy używasz miejsc po przecinku.
Jeśli utworzysz klasę walutową, możesz umieścić tam całą logikę związaną z pieniędzmi, w tym poprawną metodę ToString () - większą kontrolę nad wartościami parsowania i lepszą kontrolę podziałów.
Ponadto w przypadku klasy walut nie ma szans na niezamierzone pomieszanie pieniędzy z innymi danymi.
Inną opcją (zwłaszcza jeśli wybierasz własną klasę) jest użycie int lub int64 i oznaczenie czterech niższych cyfr (lub nawet 2) jako „po prawej stronie przecinka”. Więc „na krawędziach” będziesz potrzebować trochę „* 10000” przy wejściu i trochę „/ 10000” przy wyjściu. Jest to mechanizm przechowywania używany przez SQL Server Microsoftu, patrz http://msdn.microsoft.com/en-au/library/ms179882.aspx
Zaletą tego jest to, że wszystkie sumowania można dokonać za pomocą (szybkiej) arytmetyki liczb całkowitych.
Większość aplikacji, z którymi pracowałem, decimal
reprezentuje pieniądze. Jest to oparte na założeniu, że wniosek nigdy nie będzie dotyczył więcej niż jednej waluty.
To założenie może opierać się na innym założeniu, że aplikacja nigdy nie będzie używana w innych krajach o różnych walutach. Widziałem przypadki, w których okazało się to nieprawdą.
Teraz to założenie jest kwestionowane w nowy sposób: nowe waluty, takie jak Bitcoin, stają się coraz bardziej powszechne i nie są specyficzne dla żadnego kraju. Nie jest nierealne, że aplikacja używana tylko w jednym kraju może nadal wymagać obsługi wielu walut.
Niektórzy powiedzą, że tworzenie, a nawet używanie tylko dla pieniędzy, to „pozłacanie” lub zwiększanie złożoności poza znane wymagania. Definitywnie się z tym nie zgadzam. Im bardziej wszechobecna jest koncepcja w Twojej domenie, tym ważniejsze jest podjęcie rozsądnego wysiłku, aby użyć właściwej abstrakcji z góry. Jeśli chcesz zobaczyć złożoność, spróbuj pracować w aplikacji, która była używana, decimal
a teraz Currency
obok każdej decimal
właściwości znajduje się dodatkowa właściwość.
Jeśli użyjesz niewłaściwej abstrakcji z góry, zastąpienie jej później będzie sto razy więcej pracy. Oznacza to potencjalne wprowadzenie defektów do istniejącego kodu, a najlepsze jest to, że defekty te prawdopodobnie będą obejmować kwoty pieniężne, transakcje z pieniędzmi lub po prostu cokolwiek z pieniędzmi.
I nie jest tak trudno używać czegoś innego niż dziesiętny. Google „nuget money type” i zobaczysz, że wielu programistów stworzyło takie abstrakcje (w tym ja). To proste. Jest to tak proste, jak użycie DateTime
zamiast przechowywania daty w string
.
Stwórz własną klasę. Wydaje się to dziwne, ale typ .Net jest nieodpowiedni do obsługi różnych walut.