Niedawno wdrożyliśmy system, który musi obsługiwać wartości w wielu walutach i przeliczać między nimi, i na własnej skórze odkryliśmy kilka rzeczy.
NIGDY NIE UŻYWAJ PUNKTÓW ZMIENNYCH DO PIENIĘDZY
Arytmetyka zmiennoprzecinkowa wprowadza niedokładności, których można nie zauważyć, dopóki czegoś nie schrzanią. Wszystkie wartości powinny być przechowywane jako liczby całkowite lub typy ze stałymi dziesiętnymi, a jeśli zdecydujesz się użyć typu stałego dziesiętnego, upewnij się, że dokładnie rozumiesz, co ten typ robi pod maską (tj. Czy wewnętrznie używa liczby całkowitej czy zmiennoprzecinkowej rodzaj).
Kiedy musisz wykonać obliczenia lub konwersje:
- Konwertuj wartości na zmiennoprzecinkowe
- Oblicz nową wartość
- Zaokrąglij liczbę i zamień ją z powrotem na liczbę całkowitą
Podczas konwertowania liczby zmiennoprzecinkowej z powrotem na liczbę całkowitą w kroku 3, nie rzucaj jej po prostu - użyj funkcji matematycznej, aby ją najpierw zaokrąglić. Zwykle tak będzie round
, chociaż w szczególnych przypadkach może to być floor
lub ceil
. Poznaj różnicę i rozważnie wybierz.
Przechowuj typ liczby obok wartości
Może to nie być tak ważne dla Ciebie, jeśli obsługujesz tylko jedną walutę, ale było to dla nas ważne w przypadku obsługi wielu walut. Użyliśmy 3-znakowego kodu waluty, takiej jak USD, GBP, JPY, EUR itd.
W zależności od sytuacji pomocne może być również przechowywanie:
- Czy liczba jest przed czy po opodatkowaniu (i jaka była stawka podatku)
- Czy liczba jest wynikiem konwersji (i z czego została przekonwertowana)
Poznaj granice dokładności liczb, z którymi masz do czynienia
W przypadku wartości rzeczywistych chcesz być tak dokładny, jak najmniejsza jednostka waluty. Oznacza to, że nie masz wartości mniejszych niż cent, pens, jen, torfowisko itp. Nie przechowuj wartości z większą dokładnością niż ta bez powodu.
Wewnętrznie możesz wybrać mniejsze wartości, w takim przypadku jest to inny typ wartości waluty . Upewnij się, że twój kod wie, który jest który i nie pomieszał ich. Unikaj używania wartości zmiennoprzecinkowych nawet tutaj.
Dodając wszystkie te zasady razem, zdecydowaliśmy się na następujące zasady. W działającym kodzie waluty są przechowywane przy użyciu liczby całkowitej dla najmniejszej jednostki.
class Currency {
String code; // eg "USD"
int value; // eg 2500
boolean converted;
}
class Price {
Currency grossValue;
Currency netValue;
Tax taxRate;
}
W bazie danych wartości są przechowywane jako ciąg w następującym formacie:
USD:2500
To przechowuje wartość 25,00 $. Byliśmy w stanie to zrobić tylko dlatego, że kod zajmujący się walutami nie musi znajdować się w samej warstwie bazy danych, więc wszystkie wartości można najpierw przekonwertować na pamięć. Inne sytuacje bez wątpienia nadają się do innych rozwiązań.
A jeśli nie wyjaśniłem tego wcześniej, nie używaj pływaka!