Бессовестный плагин: я не знаю, есть ли способ сделать это с библиотекой moneyphp/money
, но вот как вы можете справиться с этой ситуацией с brick/money (отказ от ответственности: я ее автор).
Вариант, который вы выберете, будет зависеть от того, чего вы пытаетесь достичь.
Вариант 1: используйте деньги со шкалой по умолчанию, округляя вверх или вниз
Используйте этот метод, если вам нужен результат в масштабе по умолчанию для валюты (2 десятичных знака для USD
) и вы знаете, какое округление применить:
use Brick\Money\Money;
use Brick\Math\RoundingMode;
$invoiceTotal = Money::ofMinor('155', 'USD'); // USD 1.55
// or
$invoiceTotal = Money::of('1.55', 'USD');
$taxRate = '0.065'; // prefer strings over floats!
$totalWithTax = $invoiceTotal->multipliedBy($taxRate, RoundingMode::DOWN); // USD 0.10
$totalWithTax = $invoiceTotal->multipliedBy($taxRate, RoundingMode::UP); // USD 0.11
У вас есть еще много режимов округления на выбор. Если вы не укажете режим округления и результат не укладывается в 2 знака после запятой, вы получите исключение.
Вариант 2: используйте деньги с пользовательским масштабом
Если вам нужно работать с заданной точностью, скажем, с 5 знаками после запятой, вы можете указать это при создании Money:
use Brick\Money\Money;
use Brick\Money\Context\CustomContext;
use Brick\Math\RoundingMode;
$invoiceTotal = Money::of('1.55', 'USD', new CustomContext(5)); // USD 1.55000
$taxRate = '0.065';
$totalWithTax = $invoiceTotal->multipliedBy($taxRate); // USD 0.10075
Если результат не соответствует 5 знакам после запятой, вам нужно указать RoundingMode
, иначе вы получите исключение.
Вариант 3: используйте деньги с автоматическим масштабированием
Используйте этот метод, чтобы автоматически настроить масштаб результата на правильное количество знаков после запятой:
use Brick\Money\Money;
use Brick\Money\Context\AutoContext;
use Brick\Math\RoundingMode;
$invoiceTotal = Money::of('1.55', 'USD', new AutoContext()); // USD 1.55
$taxRate = '0.065';
$totalWithTax = $invoiceTotal->multipliedBy($taxRate); // USD 0.10075
Режим округления не задействован, но если деление дает десятичное число с бесконечным числом цифр, вы получите исключение.
Вариант 4: использовать RationalMoney
RationalMoney
— это денежный объект, который представляет свою сумму в виде рационального числа (доли). Это особенно полезно, когда вам нужно объединить несколько операций без округления:
use Brick\Money\Money;
use Brick\Math\RoundingMode;
$amount = Money::of('1.55', 'USD'); // USD 1.55
$amount = $amount->toRational(); // USD 155/100
$amount = $amount->dividedBy(3); // USD 155/300
$amount = $amount->dividedBy(7); // USD 155/2100
После того, как вы выполнили все свои операции, вы можете преобразовать ваше окончательное число в десятичное число Денег, при необходимости используя режим округления:
use Brick\Money\Context\DefaultContext;
use Brick\Money\Context\CustomContext;
$amount->to(new DefaultContext(), RoundingMode::DOWN); // USD 0.07
$amount->to(new CustomContext(6), RoundingMode::DOWN); // USD 0.073809
Заключительные соображения
Пакет brick/money предлагает форматирование, округление денежных средств, распределение денег, конвертацию валюты и многое другое. Он основан на пакете brick/math, который выполняет вычисления с числами любого масштаба. Попробуйте!
person
BenMorel
schedule
08.10.2018