Re: Converting floats to ints with intval

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux