PHP floating point multiplication and comparison issue [duplicate] - php

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 3 years ago.
I have a simple comparison in my code:
[simplified]
if (1.7 >= 17 * 0.1) {
echo '1.7 is greater than or equal to ' . 17 * 0.1;
} else {
echo '1.7 is NOT greater than or equal to ' . 17 * 0.1;
}
It gives the result:
1.7 is NOT greater than or equal to 1.7
I wonder can anybody explain this?

This is because native operator are indeed interpreted in base 2, and most base 10 decimal converts badly in base 2.
If you need precision, you need to either only manipulate integers (converts perfectly to base 2) or use a dedicated lib such as bcmath (I wrote a wrapper to ease bcmath usage Math)

Related

PHP show one decimal place issue [duplicate]

This question already has answers here:
Delete digits after two decimal points, without rounding the value
(15 answers)
Closed 3 years ago.
I'm trying to show one decimal place for rating number I have
but it returns unexpected value.
I used number_format and the round functions and both have the same issue, or i'm doing something wrong.
I tried to make this number show one decimal number
4.96 and it always returns 5 instead of 4.9
number_format(4.96, 1)
round(4.96, 1)
round(4.96, 1,PHP_ROUND_HALF_DOWN)
both functions returns 5 instead of 4.9
I searched all answers but couldn't find anything helpful.
Rounding 4.96 will round .9 up, so it will be 5 in all cases. If you want to do it without rounding, you may have to tweak it a bit to fool it:
floor(4.96 * 10) / 10; // 4.9
Here's a function you can use to achieve this.
function convertToSingleDecimal($num, $precision = 2) {
return floor($num) . substr(str_replace(floor($num), '', $num), 0, $precision + 1);
}
print convertToSingleDecimal("4.96", 1);

array_sum PHP wrong result [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Closed 3 years ago.
the result of this should be zero!
echo array_sum([-61.50,50.00,10.50,1.00,0.00,50.00,-16.73,-20.00,-55.75,42.48]);
Why is giving -7.105427357601E-15?
Just try round(), you will get the same result.
echo round(array_sum([-61.50,50.00,10.50,1.00,0.00,50.00,-16.73,-20.00,-55.75,42.48]));
Because floating point values (which you have here when you use decimals) are not exact. They're approximations.
The error in that approximation comes out to -7.105427357601E-15 when summing these values.
It's because of floats. If you want to calculate something with precision 2 (for this example) you should use something like this:
$el = [-61.50,50.00,10.50,1.00,0.00,50.00,-16.73,-20.00,-55.75,42.48];
$sum = 0;
foreach ($el as $e) {
$sum += $e * 100;
}
echo $sum / 100;
You should never trust to float values. Another example from Javascript (Google developer Console):

PHP doesn't produce correct output while casting a double to an integer [duplicate]

This question already has answers here:
Why are floating point numbers printed so differently?
(5 answers)
Is floating point math broken?
(31 answers)
Closed 4 years ago.
I have a situation where I cast a double variable to integer. and its giving me wrong result. Why is this happening?
>>> $amount = (double) 1052.10
=> 1052.1
>>> $amount = $amount * 100;
=> 105210.0
>>> (int) $amount;
=> 105209 // weird
I am able to fix it by rounding the variable first ( ie: (int) round($amount)),
But still, I wonder why is this happening?
using PHP 7.2.9
The 'warning' section here states:
Additionally, rational numbers that are exactly representable as floating point numbers in base 10, like 0.1 or 0.7, do not have an exact representation as floating point numbers in base 2, which is used internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal binary counterparts without a small loss of precision.

PHP (int) / braces mathematically wrong - Possible Bug? [duplicate]

This question already has answers here:
int((0.1+0.7)*10) = 7 in several languages. How to prevent this?
(7 answers)
Closed 9 years ago.
Me and my colleges were discussing the following problem, and although we came up with some theories we are still seeing it very odd...
<?php
echo (int) ((0.1 + 0.7) * 10);
?>
outputs 7
whilst
<?php
echo (int) (0.1 + 0.7) * 10;
?>
outputs 8 (as expected and as would output if you do it with a calculator)
Could the (int) be causing the issue here? Anyone have an idea?
Thanks a lot and Good Day!
The cast to integer (and related rounding error) occurs at a different point in the formula
Calculate 0.1 plus 0.7, multiply by 10 and cast to integer;
with the expected rounding error, should result in 7
against
Calculate 0.1 plus 0.7, cast to integer, and multiply by 10
casting 0.1 + 0.7 (ie 0.8) to integer should give 0, which multiplied by 10 is still 0

PHP unexpected integer/float calculation [duplicate]

This question already has an answer here:
The accuracy of PHP float calculate
(1 answer)
Closed 9 years ago.
<?php
echo (int) ((0.1 + 0.7) * 10);
Why does this output 7 instead of expected 8 ?
From the PHP manual:
... This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9999999999999991118....
It's much recommended to use the bcmath functions if you want accuracy.
As said in the comments. 0.1 + 0.7 is not actually 0.8 it is stored as something like 0.79999999. When you cast it to an int, it will truncate the decimal and just output 7. If you don't cast it to an int it wont truncate and output the expected value.
echo (0.1 + 0.7);
echo ((0.1 + 0.7) * 10);
echo (int) ((0.1 + 0.7) * 10);
Output:
0.8
8
7
Note the very large warning on floating point numbers in the PHP Guide. It pretty much is the exact example you are asking about.
To get past the int truncation problem, use round(), with specified precision
echo round(0.09+0.7,1)*10;
8
This will give you an integer, unlike just omitting the round() or int() in the case of
echo (0.09+0.7)*10;
7.9

Categories