Czy w przypadku kwot w dolarach należy używać typu danych Float czy Decimal?
Odpowiedź jest prosta. Nigdy nie pływa. NIGDY !
Liczby zmiennoprzecinkowe były zgodnie z IEEE 754 zawsze binarne, tylko nowy standard IEEE 754R zdefiniował formaty dziesiętne. Wiele ułamkowych części binarnych nigdy nie może równać się dokładnej reprezentacji dziesiętnej.
Dowolną liczbę binarną można zapisać jako m/2^n
(m
, n
liczby całkowite dodatnie), dowolna liczba dziesiętna jako m/(2^n*5^n)
.Ponieważ w plikach binarnych brakuje pierwszego factor 5
, wszystkie liczby binarne mogą być dokładnie reprezentowane przez ułamki dziesiętne, ale nie odwrotnie.
0.3 = 3/(2^1 * 5^1) = 0.3
0.3 = [0.25/0.5] [0.25/0.375] [0.25/3.125] [0.2825/3.125]
1/4 1/8 1/16 1/32
W rezultacie otrzymujesz liczbę wyższą lub niższą niż podana liczba dziesiętna. Zawsze.
Dlaczego to ma znaczenie? Zaokrąglanie.
Zaokrąglenie normalne oznacza 0..4 w dół, 5..9 w górę. A więc tak ma znaczenie, jeśli wynik to albo 0.049999999999
.... lub 0.0500000000
... Możesz wiedzieć, że oznacza to 5 centów, ale komputer tego nie wie i zaokrągla 0.4999
... w dół (źle) i 0.5000
... w górę (w prawo).
Biorąc pod uwagę, że wynik obliczeń zmiennoprzecinkowych zawsze zawiera małe wartości błędów, decyzja jest czysta. Staje się to beznadziejne, jeśli chcesz obsługiwać dziesiętne zaokrąglanie do par z liczbami binarnymi.
Nieprzekonany? Upierasz się, że w Twoim systemie kont wszystko jest w porządku? Aktywa i pasywa są równe? Ok, następnie weź każdą z podanych sformatowanych liczb każdego wpisu, przeanalizuj je i zsumuj z niezależnym systemem dziesiętnym!
Porównaj to z sformatowaną sumą. Ups, coś jest nie tak, prawda?
Do tych obliczeń wymagana była ekstremalna dokładność i wierność (użyliśmy Oracle'sFLOAT), abyśmy mogli zarejestrować „miliardową część grosza”.
To nie pomaga w rozwiązaniu tego błędu. Ponieważ wszyscy ludzie automatycznie zakładają, że komputer sumuje prawidłowo i praktycznie nikt nie sprawdza niezależnie.