Лучшая практика для работы со значениями валюты в PHP? - PullRequest
31 голосов
/ 29 сентября 2010

Мне нужно добавить, умножить и сравнить значения валют в PHP, и нужно быть уверенным, что оно точно с точностью до одного цента.

Один из способов - хранить все в float, использовать раунд до и послекаждая операция и разум машины эпсилон при сравнении на равенство.Довольно громоздкий imho.

Другой способ - хранить все это в виде центов в целочисленных типах данных, а также не забывать конвертировать туда и обратно каждый раз, когда я работаю с базой данных (mysql, где я использую десятичный тип данных).Неэлегатный и много ошибок, imho.

Другой способ - изобрести мой собственный «тип данных», сохранить все значения в строках («34.12») и создать свои собственные математические функции замены.Эти функции будут внутренне преобразовывать значение в целые числа, выполнять вычисления и выводить результат снова в виде строк.Удивительно сложно, imho.

Мой вопрос: как лучше всего работать с валютными значениями в PHP?Спасибо!

Ответы [ 4 ]

25 голосов
/ 29 сентября 2010

Начиная с MySQL v5.0.3, тип данных MySQLs DECIMAL хранит точное десятичное число, т. Е. Не является неточным представлением с плавающей запятой.

Чтобы правильно манипулировать точными числами в PHP, используйте математические вычисления произвольной точности функции .Внутренне эта библиотека манипулирует текстовыми строками.

Валюта предназначена для хранения в виде десятичного числа, вы можете получить денежные единицы меньше, чем центы.Вы должны округлять любые значения только при отображении цифр, а не во время манипуляции или хранения.

4 голосов
/ 21 января 2013

Позвольте мне ответить на это сам.Лучшей практикой будет создание класса «сумма денег».Этот класс хранит сумму внутри в виде центов в целых числах и предлагает методы получения, установки, математические функции, такие как сложение, вычитание и сравнение.Гораздо чище.

3 голосов
/ 29 сентября 2010

Обновление 2016:

Пару лет спустя и, надеюсь, немного мудрее;)
Поскольку этот ответ все еще получает время от времени голосование "за" и "против", я почувствовал необходимость пересмотреть мой ответ. Я абсолютно не советую хранить деньги как целые числа. Единственный верный ответ Эндрю Данна: используйте тип DECIMAL Mysql и инкапсулируйте функции php bc_ * в классе Currency.


Я буду держать мой устаревший ответ здесь для полноты информации

Вы всегда должны работать с целыми числами. Сохраните значения как целые в вашей базы данных, используйте целочисленные значения, чтобы делать вычисления и когда, и только когда, Вы хотите напечатать это, преобразовать это в некоторый читаемый формат.

Таким образом, вы полностью обойдете проблемы с плавающей запятой, которые, как правило, это большая проблема при работе с деньгами;)

Редактировать: Стоит упомянуть одну вещь: вы должны думать о точности прежде чем начать работать таким образом. Как уже отмечали другие, вы может потребоваться работать со значениями меньше цента, поэтому вам нужно сделать ваше умножение / деление соответственно. (т.е. валюта * 1000 за Точность .001)

0 голосов
/ 29 сентября 2010

Сохраняйте значения в виде центов и используйте целые числа. Напишите классы или вспомогательные функции для инкапсуляции отображения в пользовательском интерфейсе и обработки значений в запросах базы данных. Если вы используете float, существует слишком большой риск, что вы потеряете где-то цент.

...