Basic Idea
Decimals in PHP are essentially float by default. This can come with a few caveats.
See the following example:
$decimalOne = 0.10;
$decimalTwo = 0.20;
$decimalAdded = $decimalOne + $decimalTwo;
Actual value: 0.30000000000000004
Now lets compare that with 0.3
somewhere:
$balance = 0.30 - $decimalAdded;
$positiveBalance = $balance >= 0; // We count 0 as OK
Positive balance: NO
Value objects
So in order to have a better handling of those values, using strings is recommended. But even strings are not easy to work with often. Using a value object can overcome also those issues and provide a clear API.
use PhpCollective\DecimalObject\Decimal;
$decimalOne = Decimal::create('0.10');
$decimalTwo = Decimal::create('0.20');
$decimalAdded = $decimalOne->add($decimalTwo);
Actual value: 0.30
Internal object result
PhpCollective\DecimalObject\Decimal Object
(
[value] => 0.30
[scale] => 2
)
It also keeps track of the scale and therefore on output will also give the correct (expected) precision/scale for each value if needed.
Now let's try the founds check again:
$balance = Decimal::create('0.30')->subtract($decimalAdded);
$positiveBalance = !$balance->isNegative(); // We count 0 as OK
Positive balance: YES
See this for basic examples and API details.