numfmt_format_currency(new NumberFormatter('en',2), 31.005, "USD")
This code outputs $31.00. But it should output $31.01.
It appears to me that PHP is ignoring to convert 0.005 to 0.01 when it comes to price format.
I was trying to fix Magento's currency format issue and I'm running into this problem on the PHP side.
31.005 is actually between two numbers, see Floating Point Precision on https://php.net/float .
> ini_set('precision', 23)
= "14"
> 31.005
= 31.00499999999999900524
(There is no number 31.005 in PHP -- and other languages.)
You need to provide the number with enough precision but as little error as necessary to match your display requirements.
This works by specifying the rounding mode, when you want 31.005 to be rounded to 31.01, that is up or halfup.
$formatter = new NumberFormatter('en', NumberFormatter::CURRENCY);
$formatter->setAttribute(
NumberFormatter::ROUNDING_MODE,
NumberFormatter::ROUND_HALFUP
);
echo $formatter->formatCurrency(31.005, 'USD'), "\n";
# Output: $31.01
This is what droopsnoot commented about.
As Olivier reminded in a comment, the default mode is halfeven, also known as banker's rounding.
Also they remark that it "would be cleaner to use explicitly" the class constant NumberFormatter::CURRENCY over of the magic number 2.
$formatter = new NumberFormatter('en', 2);
$formatter = new NumberFormatter('en', NumberFormatter::CURRENCY);
This will make your code communicate better, otherwise the 2 might be read as number of digits or precision, which is not the case here. You can find all style constants in the PHP manual.
Remark: This is nothing PHP specific, when you pass those numbers to javascript and then need to format them in Javascript, you run into the same.
Cf. Answer to "Rounding in JavaScript does not give the same result as in PHP?".