Подтвердить что ты не робот

Лучшая практика для работы с валютными ценностями в PHP?

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

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

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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

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

Ответ 3

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

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


Я сохраню свой устаревший ответ здесь ради полноты

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

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

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

Ответ 4

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

Ответ 5

Я попытался умножить числа с плавающей запятой на 100 перед всеми математическими операциями, а затем разделить на 100 перед отображением результата. (Это сработало!)

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

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