[PHP] Converting floats to ints with intval

2010-05-06 Thread Paul Waring
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.


Thanks,

Paul

--
Paul Waring
http://www.pwaring.com

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Ashley Sheridan
On Thu, 2010-05-06 at 11:24 +0100, 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.
 
 Thanks,
 
 Paul
 
 -- 
 Paul Waring
 http://www.pwaring.com
 


It's part of the rounding problem you get with most languages out there.
Why can't you compare the floating point values though? Currency should
only have one decimal place anyway.

Thanks,
Ash
http://www.ashleysheridan.co.uk




Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Paul Waring

Ashley Sheridan wrote:

It's part of the rounding problem you get with most languages out there.
Why can't you compare the floating point values though? Currency should
only have one decimal place anyway.


You can't compare floating point values because if you have, for 
example, a user-entered value of '37.12' and add that to '0.18' it won't 
necessarily be equal to '37.30'.


Currency must have two decimal places, otherwise how would you represent 
five pounds and sixteen pence (£5.16) for example?


--
Paul Waring
http://www.pwaring.com

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Ashley Sheridan
On Thu, 2010-05-06 at 11:40 +0100, Paul Waring wrote:

 Ashley Sheridan wrote:
  It's part of the rounding problem you get with most languages out there.
  Why can't you compare the floating point values though? Currency should
  only have one decimal place anyway.
 
 You can't compare floating point values because if you have, for 
 example, a user-entered value of '37.12' and add that to '0.18' it won't 
 necessarily be equal to '37.30'.
 
 Currency must have two decimal places, otherwise how would you represent 
 five pounds and sixteen pence (£5.16) for example?
 
 -- 
 Paul Waring
 http://www.pwaring.com
 


Sorry, I misread that as decimal point!

Why don't you store them as integer values and add in the decimal point
with something like sprintf() afterwards? Store the values as pence and
then you won't have any rounding problems.

Thanks,
Ash
http://www.ashleysheridan.co.uk




Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Paul Waring

Ashley Sheridan wrote:

Why don't you store them as integer values and add in the decimal point
with something like sprintf() afterwards? Store the values as pence and
then you won't have any rounding problems.


If I was designing the system from scratch, that's what I'd do. 
Unfortunately this is an add-on to a legacy system where currency values 
are already stored as strings in the database (yes, not ideal I know, 
but you have to work with what you've got).


--
Paul Waring
http://www.pwaring.com

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Pete Ford

On 06/05/10 11:52, Paul Waring wrote:

Ashley Sheridan wrote:

Why don't you store them as integer values and add in the decimal point
with something like sprintf() afterwards? Store the values as pence and
then you won't have any rounding problems.


If I was designing the system from scratch, that's what I'd do.
Unfortunately this is an add-on to a legacy system where currency values
are already stored as strings in the database (yes, not ideal I know,
but you have to work with what you've got).



Can you not just add up the floating point numbers and the round them with 
round() (http://www.php.net/manual/en/function.round.php)
Certainlay for consistent calculations I'd always use the float values for as 
long as possible...


Otherwise, why not multiply by 1000 before taking the intval, then at least you 
preserve the next decimal place.


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread David Otton
On 6 May 2010 11:52, Paul Waring p...@xk7.net wrote:

 If I was designing the system from scratch, that's what I'd do.
 Unfortunately this is an add-on to a legacy system where currency values are
 already stored as strings in the database (yes, not ideal I know, but you
 have to work with what you've got).

I don't know much about your situation, but it does sound like you
need to fix the root problem. I'd use a decimal type, and lean on the
database to do the maths.

http://dev.mysql.com/doc/refman/5.1/en/numeric-types.html

You many also find money_format() useful:

http://php.net/manual/en/function.money-format.php

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Paul Waring

David Otton wrote:

On 6 May 2010 11:52, Paul Waring p...@xk7.net wrote:


If I was designing the system from scratch, that's what I'd do.
Unfortunately this is an add-on to a legacy system where currency values are
already stored as strings in the database (yes, not ideal I know, but you
have to work with what you've got).


I don't know much about your situation, but it does sound like you
need to fix the root problem. I'd use a decimal type, and lean on the
database to do the maths.


As I said, unfortunately it's a legacy system, so I can't just change 
the database to use a different type (there are dozens of columns set up 
like this, with thousands of values already set).


--
Paul Waring
http://www.pwaring.com

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread David McGlone
On Thursday 06 May 2010 07:19:48 Paul Waring wrote:
 David Otton wrote:
  On 6 May 2010 11:52, Paul Waring p...@xk7.net wrote:
  If I was designing the system from scratch, that's what I'd do.
  Unfortunately this is an add-on to a legacy system where currency values
  are already stored as strings in the database (yes, not ideal I know,
  but you have to work with what you've got).
 
  I don't know much about your situation, but it does sound like you
  need to fix the root problem. I'd use a decimal type, and lean on the
  database to do the maths.

 As I said, unfortunately it's a legacy system, so I can't just change
 the database to use a different type (there are dozens of columns set up
 like this, with thousands of values already set).

Would It be possible to write a script to extract everything from that 
database and insert it into a database with the correct columns and values, 
then all you would need to do is change the db connection information.

-- 
Blessings,
David M.

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



RE: [PHP] Converting floats to ints with intval

2010-05-06 Thread Bob McConnell
From: David McGlone
On Thursday 06 May 2010 07:19:48 Paul Waring wrote:
 David Otton wrote:
  On 6 May 2010 11:52, Paul Waring p...@xk7.net wrote:
  If I was designing the system from scratch, that's what I'd do.
  Unfortunately this is an add-on to a legacy system where currency
values
  are already stored as strings in the database (yes, not ideal I
know,
  but you have to work with what you've got).
 
  I don't know much about your situation, but it does sound like you
  need to fix the root problem. I'd use a decimal type, and lean on
the
  database to do the maths.

 As I said, unfortunately it's a legacy system, so I can't just change
 the database to use a different type (there are dozens of columns set
up
 like this, with thousands of values already set).
 
 Would It be possible to write a script to extract everything from that

 database and insert it into a database with the correct columns and
values, 
 then all you would need to do is change the db connection information.

If the data is really stored in strings, you need to break it down into
substrings around the decimal and then convert both sides into integers
and combine them into an integer value. It is the conversion into float
that introduces the error because of the imprecise representation of
fractional decimal values in binary.

Bob McConnell

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Paul Waring

David McGlone wrote:

On Thursday 06 May 2010 07:19:48 Paul Waring wrote:

David Otton wrote:

On 6 May 2010 11:52, Paul Waring p...@xk7.net wrote:

If I was designing the system from scratch, that's what I'd do.
Unfortunately this is an add-on to a legacy system where currency values
are already stored as strings in the database (yes, not ideal I know,
but you have to work with what you've got).

I don't know much about your situation, but it does sound like you
need to fix the root problem. I'd use a decimal type, and lean on the
database to do the maths.

As I said, unfortunately it's a legacy system, so I can't just change
the database to use a different type (there are dozens of columns set up
like this, with thousands of values already set).


Would It be possible to write a script to extract everything from that 
database and insert it into a database with the correct columns and values, 
then all you would need to do is change the db connection information.


Possible, yes. Practical, no. :)

--
Paul Waring
http://www.pwaring.com

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread David McGlone
On Thursday 06 May 2010 08:39:03 Bob McConnell wrote:
 From: David McGlone

 On Thursday 06 May 2010 07:19:48 Paul Waring wrote:
  David Otton wrote:
   On 6 May 2010 11:52, Paul Waring p...@xk7.net wrote:
   If I was designing the system from scratch, that's what I'd do.
   Unfortunately this is an add-on to a legacy system where currency

 values

   are already stored as strings in the database (yes, not ideal I

 know,

   but you have to work with what you've got).
  
   I don't know much about your situation, but it does sound like you
   need to fix the root problem. I'd use a decimal type, and lean on

 the

   database to do the maths.
 
  As I said, unfortunately it's a legacy system, so I can't just change
  the database to use a different type (there are dozens of columns set

 up

  like this, with thousands of values already set).
 
  Would It be possible to write a script to extract everything from that
 
  database and insert it into a database with the correct columns and

 values,

  then all you would need to do is change the db connection information.

 If the data is really stored in strings, you need to break it down into
 substrings around the decimal and then convert both sides into integers
 and combine them into an integer value. It is the conversion into float
 that introduces the error because of the imprecise representation of
 fractional decimal values in binary.

I see.

-- 
Blessings,
David M.

-- 
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Robert Cummings

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



Re: [PHP] Converting floats to ints with intval

2010-05-06 Thread Fernando
I think Bob has a good idea here, split the string values and the 
concatenate them to make the whole value.

If the data is really stored in strings, you need to break it down into
substrings around the decimal and then convert both sides into integers
and combine them into an integer value. It is the conversion into float
that introduces the error because of the imprecise representation of
fractional decimal values in binary.

Bob McConnell

   


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php