Paul Waring wrote:
I've got the following script which demonstrates a problem I'm having
with floating point numbers and intval:
$times100 = (-37.12 * 100);
print $times100 . "\n";
$intval100 = intval($times100);
print $intval100 . "\n";
print ($intval100 / 100) . "\n";
I expect the output to be:
-3712
-3712
-37.12
However, the actual output I'm getting (on several systems, so it's not
just my machine) is:
-3712
-3711
-37.11
Is there a reason for this, and a better way I should be doing it?
Basically I need to add up a list of floats, representing currency
values, and see if they're equal to another float, but I need to convert
them to ints first because I can't guarantee than there won't be
something after the second decimal place.
This is a very well known problem in computer science:
http://en.wikipedia.org/wiki/Floating_point
To illustrate your example run the following:
<?php
$value = -37.12;
echo "Value: ".sprintf( '%f', $value )." (what you think you have)\n";
echo "Value: ".sprintf( '%f', $value )." (what the computer thinks you
have)\n\n";
$value *= 100;
echo "Value: ".sprintf( '%f', $value )." (after multiply by 100)\n";
echo "Value: ".sprintf( '%.20f', $value )." (what the computer thinks
you have)\n\n";
$value = intval( $value );
echo "Value: ".sprintf( '%d', $value )." (after type conversion to int)\n";
echo "Value: ".sprintf( '%d', $value )." (what the computer thinks you
have)\n\n";
$value /= 100;
echo "Value: ".sprintf( '%f', $value )." (after divide by 100)\n";
echo "Value: ".sprintf( '%.20f', $value )." (what the computer thinks
you have)\n\n";
?>
As you can see the values are tripped up at the multiplication stage
where the computer can't perfectly store the value -3712.0 and then this
is excerbated by the truncation of the value to an integer using
intval(). If you want to avoid this, then you should avoid the
conversion to int and use rounding for the final result.
<?php
$value = -37.12;
$value *= 100;
$value /= 100;
echo "Value: ".sprintf( '%f', $value )." (after divide by 100)\n";
echo "Value: ".sprintf( '%.20f', $value )." (what the computer thinks
you have)\n";
echo "Value: ".sprintf( '%.2f', $value )." (formatted with rounding)\n";
?>
Cheers,
Rob.
--
http://www.interjinn.com
Application and Templating Framework for PHP
--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php