-1

Can someone explain what is happening here? I have floating point number that is to be rounded to two decimal points (price).

echo $total . " is rounded to " . round((float)$total,2);
var_export((float)$total);
echo " is rounded to ";
var_export(round((float)$total,2));
echo "\r\n";

Output is: 79.95 is rounded to 79.95 79.9500000000000028421709430404007434844970703125 is rounded to 79.9500000000000028421709430404007434844970703125

So, "echo" rounds to itself. When I use var_export() to output data, seem that round() is not working.

Just for test, I made:

$total = 79.9501234576908988888;

Then I get: 79.950123457691 is rounded to 79.95 79.9501234576908927920158021152019500732421875 is rounded to 79.9500000000000028421709430404007434844970703125

So, "echo" seem to automatically round floats to 11 decimal points. Why round() is not working with var_export is a mystery.

Does anyone have an explanation?

Thanks,

Rudolf

2 Answers2

1

Floating point numbers have specific, 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.

In your case, if you use var_export, it will output (or return) a parsable string representation of a variable, which in this case will also return all the data when your data is stored as a float variable.

That's why when you execute the following

var_export(round((float)$total,2));

The system will first round up the $total to 79.95, but since you have specified the float cast, it will store it to the system's data precision and so when you use the var_export to faithfully return the data, it will give you something like

79.9500000000000028421709430404007434844970703125

On the other hand, the PHP var_export function is intelligent enough to distinguish the type of data you are trying to parse. (even if you do not use the float cast). Hence if you parse "79", the value will be regarded as an integer, if you parse "79.123", the value will be regarded as float.

Say for the following codes:

<?php
//$total = 79.9501234576908988888;
$total = 79;

echo "parsing 79";
echo "<br>";

var_export((float)$total);
echo " is rounded to ";
var_export(round((float)$total,2));
echo "<br><br>";

$total = 79.123;

echo "parsing 79.123";
echo "<br>";


var_export($total);
echo " is rounded to ";
var_export(round($total,2));
echo "<br><br>";



?>

The result will be :

parsing 79

79 is rounded to 79

parsing 79.123

79.1230000000000046611603465862572193145751953125 is rounded to 79.1200000000000045474735088646411895751953125

Ken Lee
  • 6,985
  • 3
  • 10
  • 29
  • Hmm.. But I cast to float before I do rounding, so should really get 79.9500000000000000000. Also, omitting cast to float does not change the behavior. – user1442439 Nov 20 '20 at 09:01
  • I will give you more information later. – Ken Lee Nov 20 '20 at 09:15
  • Sorry I was in metro so I need time to write a more detailed explanation. Please see my revised answer – Ken Lee Nov 20 '20 at 10:03
  • Thank you for explanation. I did ore reading and testing. INI setting "serialize_precision" is what causing the behavior. So now I know why it happens the way it happens and I can fix the system so it works. (No, I am not going to change the setting, but it crusial in understanding of the problem) – user1442439 Nov 20 '20 at 13:10
  • Yes in my understanding it is the default precision used in many servers , but it can be overridden if you wish. Great to know that you have proceeded to the next level. Happy Coding bro ! – Ken Lee Nov 20 '20 at 13:36
0

How var_export () is rounded depends on the PHP version and the system setting 'serialize_precision'. You can display the setting with:

var_dump(ini_get('serialize_precision'));

If your rights allow you can with

ini_set('serialize_precision',"-1");

change this. "-1" means that an enhanced algorithm for rounding such numbers will be used.

The instruction must always be at the beginning of your script or you can change the setting in your php.ini.

jspit
  • 7,276
  • 1
  • 9
  • 17
  • Yes, thank you. I was not aware of this setting. Now, I did more reading and played with settings to do :proof of concept" and it all makes sense – user1442439 Nov 20 '20 at 13:07