A simple calculation in php.. I'm doing it wrong? - php

I do not understand php:
echo -0.01-0.02-0.16+0.01+0.01+0.17;
result 2.7755575615629E-17
correctly = 0 !

E-17 really means x 10 ^ (-17).
According to the computer, which suffers from precision errors at the far end of decimal floating point numbers, it is calculating your answer to be 0.00000000000000002775557...
If you don't need that sort of precision, you can force rounding to a certain accuracy:
echo round(-0.01-0.02-0.16+0.01+0.01+0.17, 8);

The answer you got is accurate answer according to BODMAS rule if you want round up answer than just use round() function of PHP. You will get you answer.
echo round(-0.01-0.02-0.16+0.01+0.01+0.17, 8);

Related

PHP round() bug with round(908.5449, 2, PHP_ROUND_HALF_UP) = 908.54?

I am currently investing a rounding problem in PHP.
I've tested it here https://3v4l.org/NpRPp and it seems to be the same, since ever.
But is this correct behaviour? Because i expected the following.
echo round(908.5449, 2, PHP_ROUND_HALF_UP); // should be 908.55, but returns actually 908.54
Can someone tell if this behaviour is intended, and if so, how to solve it properly for every possible floating point number?
Edit: Thanks to the answers, this behaviour is correct but i expected the wrong result. My original number in the program was 908.55 which somewhere in the chain of the program became 908.5449999999994 due to storage in DB and floating point precision issues. So i wanted it to be 908.55 again, which does not work with regular use of round().
This is working correctly. The output of
echo round(908.5449, 2, PHP_ROUND_HALF_UP);
Should be 908.54. You're rounding to two decimals, so the remainder, that is rounded off is 0.0049. This is less than 0.005, which would be half, so it is rounded down.

PHP math with long decimals

I'm currently trying to do math with large decimals. This works fine:
<?php
$math = 99 + 0.0001;
echo $math;
?>
Output: 99.0001
However, when I try to add with decimals with more than 12 decimal places, I do not receive the expected output:
<?php
$math = 99 + 0.0000000000001;
echo $math;
?>
Output: 99
How can I make it so that if I add with a decimal that has more than 12 decimal places, that the result will still have the exact answer without rounding? For example:
<?php
$math = 99 + 0.0000000000001;
echo $math;
?>
Output: 99.0000000000001
Quick google search yielded this.
Floating point numbers have limited precision. Although it depends on
the system, PHP typically uses the IEEE 754 double precision format,
which will give a maximum relative error due to rounding in the order
of 1.11e-16.
The page I linked has lots of helpful info regarding floating point numbers in PHP as well as links to libraries which can work with arbitrary precision floating point numbers. Could be useful depending on your needs.
Edit: Also, as Mark Baker said in a comment, you may also need to specify the precision of the number you want to print in the printf() format string. Check this page out and look at number 5.

PHP very small decimals result in error

PHP is erroring out on me when working with small decimals / floats. Take the following code:
$spotPrices['entry'] = 1.6591;
$price['o'] = 1.65908;
$currentresult = $spotPrices['entry'] - $price['o'];
echo $currentresult;
I would expect this to output 0.00002 (the answer). But instead it outputs: -1.99999999999E-5
Why is it doing this and, more importantly, how can I get the correct result?
I've done some searching on the forums and seen that floating points give PHP fits but haven't seen a solution or workaround that seems to answer my question.
My calculator is saying that the result should be 0.00002
use number_format:
$currentresult = number_format($spotPrices['entry'] - $price['o'], 8);
Instead of 0.00002 you get 1.9999999999909E-5 which is 0.000019999999999909. This is due to floating point precision. Precision is platform-dependent. You can read up on it here: http://www.php.net/manual/en/language.types.float.php

php sprintf displaying wrong number

I'm having a weird problem where PHP's sprintf seems to be changing some numbers. This doesn't happen all the time, just occasionally.
The following code:
echo sprintf('%04d',$product['priceUSD']*100)."(".($product['priceUSD']*100).")";
generates the following output for a $19.99 product: 1998(1999)
I can work around this, but I'd love to know why it is doing it, and if there's any method to the apparent madness.
Update:
It looks like it's happening when converting from float to int. The following gives the same output:
echo (int)($product['priceUSD']*100)."(".($product['priceUSD']*100).")";
echo sprintf('%.2f',$product['priceUSD']*100)."(".sprintf('%.2f',$product['priceUSD']*100).")";
What number format are you looking for?
First off: %d is kinda like an (int) cast.
19.99 = 1.99899999999999984368059813278E1 = 0x4033FD70A3D70A3D
in IEEE 64 Bit.
if we multiply that in floating point with 100 we get 1998.99999999999984368059813278E1 casted to int is 1998.
"19.99 is just one of those numbers..." (see #Dragons Link)
for exact results use bcmath extension:
echo sprintf('%4d', bcmul ($price,100));
To stabilize your multiplication while facing floating point arithmetic problems, leverage the bcmul() function to multiply the two numbers.
Secondarily, I should mention that printf() will perform rounding, but (int) will not.
Code: (Demo)
$product['priceUSD'] = '19.99';
printf('%04d', bcmul($product['priceUSD'], 100));
Output:
1999

php - why does floor round down a integer?

I am confused as to why:
echo log10(238328) / log10(62);
results in 3
but
echo floor(log10(238328) / log10(62));
results in 2
I know floor rounds down but I thought it was only for decimal numbers.
How can I get an answer of 3 out of the latter statment whilst still normally rounding down?
PHP uses double-precision floating point numbers. Neither of the results of the two logarithms can be represented exactly, so the result of dividing them is not exact. The result you get is close to, but slightly less than 3. This gets rounded to 3 when being formatted by echo. floor, however returns 2.
You can avoid the inexact division by taking advantage of the fact that log(x, b) / log(y, b) is equivalent to log(x, y) (for any base b). This gives you the the expression log(238328, 62) instead, which has a floating point result of exactly 3 (the correct result since 238328 is pow(62, 3)).
It's due to the way floating point numbers are polished in PHP.
See the PHP Manual's Floating Point Numbers entry for more info
A workaround is to floor(round($value, 15));. Doing this will ensure that your number is polished quite accurately.
If you var_dump you'll see that the "3" is actually a float. Which means its probably close to 3 and rounded up. If you wanted 3, you would have to use the sister function, ceil.
You might get better results using the round() function and/or explicitly casting it to an int rather than relying on ceil(). Look here for more information: http://php.net/manual/en/language.types.integer.php
At the cost of a little performance, you could coerce it, reducing the precision to a more useful range by rounding or string formatting the number:
echo floor(round(log10(238328)/log10(62), 4));
echo floor(sprintf('%.4f', log10(238328)/log10(62)));
// output:
// 3
// 3
You should go with the minimum precision that you need. More precision is not what you want. Rounding without flooring might be more correct, the results are different depending on precision.
echo floor(round(log10(238328)/log10(62), 16));
echo round(log10(238328)/log10(62), 16);
// output:
// 2
// 3
there three functions for doing nearly the same:
ceil --> ceil(0.2)==1 && ceil(0.8)==1
floor --> floor(0.2)==0 && floor(0.8)==0
round --> round(0.2)==0 && round(0.8)==1

Categories