PHP. result of the subtraction of two floating point numbers
Asked Answered
C

2

5

For example...

$aa = 10694994.89;
$bb = 10696193.86;
$ab = $aa - $bb;
// result is:-1198.9699999988 not the -1198,97

But in this exampe:

$cc = 0.89;
$dd = 0.86;
$cd = $cc - $dd;
//Result is: 0.03

Why the difference in to examples? Lacks precision?

Chaudfroid answered 18/11, 2014 at 21:52 Comment(3)
once again: floating-point-gui.deDamselfly
Why the difference in to examples?Chaudfroid
@AndreyK. See this link: php.net/manual/en/language.types.float.php !Floating point numbers have limited precision.Ergograph
H
5

None of the numbers in your code can be expressed exactly in binary floating point. They have all been rounded somehow. The question is why one of the results has been (seemingly) rounded to two decimal digits and not the other. The answer lies in the difference between the precision and accuracy of floating point numbers and the precision PHP uses to print them.

Floating point numbers are represented by a significand (or mantissa) in the range [1, 2), which is scaled by multiplying it by a power of two. (This is what the "floating" in floating point means). The precision of the number is determined by the number of digits in the significand. The accuracy is determined by how many of those digits are actually correct. See: How are floating point numbers stored in memory? for more details.

When you echo floating point numbers in PHP, they are first converted to string using the precision configuration setting, which defaults to 14. (In Zend/zend_operators.c)

To see what is really going on, you have to print the numbers using a larger precision:

$aa = 10694994.89;
$bb = 10696193.86;
$ab = $aa - $bb;

printf ("\$aa: %.20G\n", $aa);
printf ("\$bb: %.20G\n", $bb);
printf ("\$ab: %.20G\n\n", $ab);

$cc = 0.89;
$dd = 0.86;
$cd = $cc - $dd;

printf ("\$cc: %.20G\n", $cc);
printf ("\$dd: %.20G\n", $dd);
printf ("\$cd: %.20G\n", $cd);

Output:

$aa: 10694994.890000000596
$bb: 10696193.859999999404
$ab: -1198.9699999988079071

$cc: 0.89000000000000001332
$dd: 0.85999999999999998668
$cd: 0.030000000000000026645

The initial numbers have a precision of about 16 to 17 digits. When you subtract $aa-$bb, the first 4 digits cancel each other out. The result, (while still having a precision of about 16 to 17 digits), is now only accurate to about 12 digits. This lower accuracy shows up when the results is printed using a 14-digit precision.

The other subtraction ($cc-$dd) loses only a single digit of accuracy, which isn't noticable when printed with a 14-digit precision.

Hodges answered 19/11, 2014 at 8:18 Comment(0)
E
2

This should work for you:

(You have to round your result!)

$aa = 10694994.89;
$bb = 10696193.86;
echo $ab = round($aa - $bb, 2);
Ergograph answered 18/11, 2014 at 21:57 Comment(2)
It is clear that I can to round this, but why the difference in the two examples?Chaudfroid
read the link i posted, understand how computers deal with floating-point numberDamselfly

© 2022 - 2024 — McMap. All rights reserved.