Calculation of incorrect multiplication

Asked

Viewed 715 times

5

For some reason when performing the multiple calculation by a floating value PHP always returns me the wrong value.

Example:

echo ((33 * 0.8) - 26.4);

result: 3.5527136788005E-15

But the expected result would be 0

I could not find any answer to this problem, because if I perform the calculation to get 80% of the value differently it works.

Example:

echo (((33 * 80) / 100) - 26.4);

result: 0
  • 1

    Start by reading the documentation. She explains well why it happens.

  • Maybe I can help you: http://stackoverflow.com/questions/13128769/simple-math-with-decimals-in-php

  • if you still want to use 0.8 then use echo number_format(((33 * 0.8) - 26.4),0) and if you need 2 decimal places use echo number_format((33 * 0.8) - 26.4),2)

  • @Andersoncarloswoss I also wanted to know the reason for this to happen too, it’s just any calculation, but when it’s decimal by the percentage returns this value

  • Testa http://answall.com/a/188514/3635 and let me know.

  • 2

    Moderator note: Although the linked question as duplicate is marked with the Javascript tag, the problem (and the answer) is universal for any language in the use of floating point numbers.

  • @Leocaracciolo, giving how number_format works perfectly, but I wonder why php gives this result instead of 0

  • @bfavaretto I had reopened because he wants to know how to "solve", including I had linked all these the first time I scored as dup, but I agree with you, anyway wanted to leave a reply, I just don’t know if it is the best solution for PHP.

  • Thank you all very much, it was more to know the reason, because until then I had never seen anything like it.

  • Just to confirm, you realize that 3.5527136788005E-15 is practically zero, right?

  • Yes, but always when compared with the correct value returned false, the other way I quoted in the example works perfectly.

Show 6 more comments

3 answers

7


As you already have the answer of how to get around the situation, I will leave here the excerpt from documentation which explains why this happened.

Accuracy of floating point numbers

Floating point numbers have limited accuracy. Although it relies on the system, PHP generally uses the IEEE 754 double-precision format, which will bring maximum accuracy due to rounding of the order of 1.11e-16. Unusual mathematical operations may cause larger errors, and of course the propagation of errors should be considered when several operations are performed.

In addition, rational numbers that have exact representation in numbers in base 10, such as 0.1 or 0.7, do not have exact representation in floating point in base 2, the format used internally, no matter the size of the mantissa. So there is no conversion to the internal format without a small loss of accuracy. This can lead to confusing results: for example, floor((0.1+0.7)*10) will normally return 7, instead of the expected result 8, because the final internal representation will be something like 7.9999999991118....

So never rely on results with floating point numbers up to the last house, and never compare floating point numbers on equals. If you really need high precision, you can use the mathematical functions of arbitrary precision and the functions gmp are available.

For a "simple" explanation of this question, see » guide on floating point, which also has the alternate title "Because my numbers don’t add up right?".

  • because it is echo number_format((0.1 + 0.2),22); it is giving 0.3000000000000000444089

4

3

One of the easy ways to get around this is to use the BC Math.

Thus the ((33 * 0.8) - 26.4) would be:

bcscale(2);
echo bcsub(bcmul('33', '0.8'), '26.4');

// O resultado será de `0.00`.

Test this.

The bcsub() will subtract the 26.4 of the resulting value of bcmul(). The bcmul() is responsible for multiplying the 33 for 0.8, containing 2 digits after the comma, defined bybcscale(2);, in this case.

In the absence of a definition of bcscale standard 0 will be used, making 5.7 - 4.3 = 1 instead of 1.4, for example.


If you want to compare values you can use bccomp(), it works in a similar way to spacecraft operator (<=>), where you return 0 if it is equal, -1 the left side is larger or 1 if the right side is larger, Test this.

echo bccomp(bcmul('33', '0.8', 2), '26.4', 2);

// O resultado será de `0`.

All documentation of the bc* is in http://php.net/manual/en/ref.bc.php, as indicated by @Anderson Carlos Woss.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.