Intereting Posts
Перемещение нескольких массивов в один массив Является ли это разумным способом обработки getters / seters в классе PHP? Установка расширения ImageMagick с помощью php / windows Блокировка базы данных MySQL, чтобы только один человек мог запустить запрос? Почему переменная не может начинаться с номера? .htaccess php_value auto_prepend_file делает ошибку 500. Как я могу это исправить? Шведские символы и формы входа PHP / MYSQL Лучший способ проверки URL-адреса в PHP сопоставить шаблон url в php с использованием регулярного выражения если пустое значение $ _POST присваивает значение в цикле foreach Как установить обычную общую сумму перед оформлением заказа в magento? Использование Datetime в качестве значений по оси X в графиках Google Могу ли я каким-то образом узнать, какая замена происходит из-за обратного вызова preg_replace_callback? Номер страницы с разбивкой по страницам firebase PHP: создать пользователя

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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