2010-09-29 8 views
27

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

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

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

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

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

ответ

5

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

+3

Это не совсем простая практика и очень плохая совет. Пожалуйста, непременно инкапсулируйте функции, которые работают с функциями произвольной точности математики, но, пожалуйста, не следуйте приведенным выше советам. Лучший ответ - Эндрю Данн. –

3

Update 2016:

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


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

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

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

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

+2

MySQL и другие имеют формат DECIMAL/NUMERIC, который разработан специально для того, чтобы обойти проблемы с плавающей точкой и дать точные результаты. –

+3

Я принял иронию, поэтому я не проголосовал за тебя. Пожалуйста, подтвердите, что я был прав :) – thomasmalt

+1

@Tatu Ulmanen: Конечно, Mysql делает. Но если вы затем зайдете и сделаете что-то вроде проверки равенства в php, вы можете получить неожиданные результаты. –

22

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

Для правильной обработки чисел точности в PHP используйте arbitrary precision math functions. Внутренне эта библиотека манипулирует текстовыми строками.

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

+1

Извините, но я вас не понимаю. В php нет десятичного типа данных. Если вы имели в виду float: вы не можете надежно проверить их использование. – CruftyCraft

+10

PHP имеет набор функций, предназначенных специально для манипуляции и сравнения чисел точности: http://www.php.net/manual/en/ref.bc.php –

0

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

Смежные вопросы