2010-09-29 12 views
27

Potrzebuję dodawać, mnożyć i porównywać wartości walut w PHP i trzeba mieć pewność, że jest on dokładny do jednego centa.Najlepsza praktyka do pracy z wartościami walut w PHP?

Jednym ze sposobów jest przechowywanie wszystkiego w float, użyj rundy przed i po każdej operacji i epsilon maszyny umysłu przy porównywaniu dla równości. Dość nieporęczny imho.

Innym sposobem jest zapisanie całej zawartości jako centów w liczbach całkowitych, a także pamiętaj, aby konwertować tam iz powrotem w każdym momencie pracy z bazą danych (mysql, gdzie używam typu danych dziesiętnych). Inelegant i wiele pułapek błędów, imho.

Innym sposobem jest wymyślenie własnego "typu danych", zapisanie wszystkich wartości w ciągach znaków ("34.12") i utworzenie własnych matematycznych funkcji zastępowania. Ta funkcja przekształci wewnętrznie wartość na liczbę całkowitą, wykona obliczenia i ponownie wyświetli wynik łańcuchów. Zaskakująco skomplikowany, imho.

Moje pytanie: jaka jest najlepsza praktyka w pracy z wartościami walut w PHP? Dzięki!

Odpowiedz

5

Pozwól mi odpowiedzieć sam. Najlepszą praktyką byłoby stworzenie klasy "ilość pieniędzy". Klasa ta przechowuje wartość wewnętrznie jako centy w liczbach całkowitych i oferuje funkcje pobierające, ustawiające, funkcje matematyczne, takie jak dodawanie, odejmowanie i porównywanie. Znacznie czystsze.

+3

To nie jest po prostu najlepsza praktyka i bardzo złe Rada. Proszę, za wszelką cenę, zamknąć funkcje, które działają z dowolnie precyzyjnymi funkcjami matematycznymi, ale proszę nie stosować się do powyższych rad. Najlepszą odpowiedzią jest Andrew Dunn. –

3

Aktualizacja 2016:

Kilka lat później i mam nadzieję, że trochę mądrzejszy;)
Od tej odpowiedzi wciąż otrzymuje okolicznościowy górę iw dół głosowaniu czułem potrzebę przeglądu moją odpowiedź. Absolutnie nie radzę przechowywać "pieniędzy" jako liczb całkowitych. Jedyną prawdziwą odpowiedzią jest Andrew Dunna: Użyj typu DECIMAL Mysql i zamknij funkcje bc_ * php w klasie Currency.


będę moje przestarzałe odpowiedzi tutaj dla kompletności sake

Należy zawsze pracować z liczbami całkowitymi. Zapisz wartości jako ints w swojej bazie danych, użyj ints do wykonywania obliczeń i kiedy i tylko wtedy, gdy chcesz je wydrukować, przekonwertuj je do pewnego czytelnego formatu.

ten sposób completeley obejścia pływających problemy punkt, który, ogólnie, jest to duży problem podczas pracy z pieniędzmi;)

Edit: Jedno warto wspomnieć: Trzeba myśleć o precyzji przed rozpoczęciem pracy tą drogą. Jak zauważyli inni, możesz potrzebować pracować z wartościami mniejszymi niż cent, więc musisz odpowiednio wykonać mnożenie/dzielenie . (Czyli waluty * 1000 dla dokładnością .001)

+2

MySQL i inne mają format DECIMAL/NUMERIC, który został zaprojektowany specjalnie w celu ominięcia problemów z zmiennoprzecinkowymi i podania dokładnych wyników. –

+3

Przyjąłem ironię, więc nie głosowałem. Potwierdź, że miałem rację :) – thomasmalt

+1

@Tatu Ulmanen: Jasne, Mysql ma. Ale jeśli przejdziesz dalej i zrobisz coś takiego jak testowanie równości w php, możesz uzyskać nieoczekiwane rezultaty. –

22

Jak MySQL v5.0.3, MySQLs DECIMAL typów danych przechowuje dokładną liczbę dziesiętną, to znaczy nie jest niedokładny zmiennoprzecinkowych punkt reprezentacji.

Aby poprawnie manipulować liczbami dokładnymi w PHP, należy użyć arbitrary precision math functions. Wewnętrznie ta biblioteka manipuluje ciągami tekstowymi.

Waluta ma być przechowywana jako liczba dziesiętna, można uzyskać jednostki pieniężne mniejsze niż centy. Powinieneś zaokrąglać dowolne wartości tylko podczas wyświetlania liczb, a nie podczas manipulacji lub przechowywania.

+1

Przykro mi, ale cię nie rozumiem. W php nie ma typu danych dziesiętnych. Jeśli miałeś na myśli float: nie możesz wiarygodnie przetestować równości, używając ich. – CruftyCraft

+10

PHP ma zestaw funkcji zaprojektowanych specjalnie do manipulowania i porównywania liczb precyzyjnych: http://www.php.net/manual/en/ref.bc.php –

0

Zachowaj wartości jako centy i użyj liczb całkowitych.Napisz klasy lub funkcje pomocnicze, aby zamknąć wyświetlanie w interfejsie i zarządzać wartościami w zapytaniach do bazy danych. Jeśli używasz float, istnieje zbyt duże ryzyko, że stracisz gdzieś cent.

Powiązane problemy