Re: Converting floats to ints with intval
| From: | Robert Cummings | Date: | Thu, 06 May 2010 13:57:28 +0000 |
| Subject: | Re: Converting floats to ints with intval | ||
| References: | 1 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-304957@lists.php.net to get a copy of this message | ||
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_pointTo 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