0

How to type hint prices in PHP?

My example function:

function dividePrice(float $a, float $b) : float
{
    return $a / $b;
}

echo dividePrice(132.32, 23.24);

This return: 5.6936316695353

Is it safe and well calculated if I use float for type hinting? If not float how to do it?

zero323
  • 322,348
  • 103
  • 959
  • 935
hage
  • 1
  • What kind of prices? Some currencies don't have decimal points, or even fractional amounts. If only USD, then a price is a float anyway you look at it, and you just have to force round to string or restricted decimal length (if storing in db). – IncredibleHat Nov 17 '18 at 16:04
  • Only USD. In DB should be as decimal, but in PHP? – hage Nov 17 '18 at 16:52

1 Answers1

0

Floating point numbers have inherent rounding issues, as a lot of decimal numbers cannot be represented exactly in floating point, and are only close approximations.


To represent money in PHP, I can only advise to use a proper money library that performs exact calculations, and handles rounding explicitly.

Example with brick/money, a library I authored:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$money = Money::of('132.32', 'USD');
echo $money->dividedBy('23.24', RoundingMode::HALF_UP); // USD 5.69

This library is based on brick/math, a library that performs exact calculations on numbers of any size. You can also use the brick/math library directly to pass exact decimal numbers around in your code:

use Brick\Math\BigDecimal;
use Brick\Math\RoundingMode;

$a = BigDecimal::of('132.32');
$b = BigDecimal::of('23.24');

// Dividing to 2 decimals
echo $a->dividedBy($b, 2, RoundingMode::HALF_UP); // 5.69

// Dividing to 20 decimals
echo $a->dividedBy($b, 20, RoundingMode::HALF_UP); // 5.69363166953528399312

To reiterate, floats are designed to perform approximate calculations. Don't use them for money handling.

An alternative would be to use int to represent money, in cents (you still have to be careful with division, though). But I can only encourage you to use a well-established library to make your code more readable and less prone to errors.

BenMorel
  • 34,448
  • 50
  • 182
  • 322