Мне нужно добавить, умножить и сравнить валютные значения в 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, существует слишком много риска, что вы потеряете нигде.