GIDForums  

Go Back   GIDForums > Computer Programming Forums > MySQL / PHP Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 23-Oct-2006, 11:03
JdS's Avatar
JdS JdS is offline
Senior Member
 
Join Date: Aug 2001
Location: KUL, Malaysia
Posts: 3,371
JdS will become famous soon enough

The mystery of 9.95


I have this script that will accept a price off a web form. Since it's a price, I prefer to save the information to the database as an integer, in other words, in cents.

For some strange, unknown reason, when I test the script and submit a price like 9.95, the script will end up with 994 cents!

Here's an example script you can run yourself:

PHP Code:

<?php
if( isset($_POST['price'])  &&  $_POST['price'] )
{
    $price['dollars'] = floatval( trim($_POST['price']) );
    $price['cents'] = intval( $price['dollars']*100 );
    printf( "<p>\$%s is %d cents.</p>", $price['dollars'], $price['cents'] );
    $form_price_value = &$price['dollars'];
}
else
{
    $form_price_value = null;
}
echo     "<form method=\"post\" action=\"$_SERVER[PHP_SELF]\">"
        .     "<p>Price: <input type=\"text\" name=\"price\" value=\"$form_price_value\" /></p>"
        .     "<p><input type=\"submit\" name=\"submit\" value=\"How much is that in cents?\" /></p>"
        . "</form>"
?>


If you submit 9.95 or 8.95, the results will be 994 and 894 respectively. However anything else will be fine, e.g. 6.95, 7.95, 3.95 etc.

I thought it was a Windows issue... but I find the same result(s) testing the example script above, on this web server (Linux).

It can't be the browsers either. Same results on both, FF and IE.

Anybody with a suggestion?
  #2  
Old 23-Oct-2006, 11:47
TurboPT's Avatar
TurboPT TurboPT is offline
Regular Member
 
Join Date: Feb 2006
Location: Atlanta, GA
Posts: 926
TurboPT is a jewel in the roughTurboPT is a jewel in the roughTurboPT is a jewel in the rough

Re: The mystery of 9.95


What about just a straight:
PHP Code:

$someVar = $_POST['price'] * 100; 


It was also interesting that your example for 19.99 returned 19.98, but the above snippet gives 1999. (and 995 for the original amount)
__________________
Use the force...read the source!!
WYCIWYG -- what you code is what you get!
  #3  
Old 23-Oct-2006, 11:57
LuciWiz's Avatar
LuciWiz LuciWiz is offline
Moderator
 
Join Date: Jul 2004
Location: Cluj-Napoca (Romania)
Posts: 889
LuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the rough

Re: The mystery of 9.95


The problem has to do with floating point precision; see the manual page for PHP discussing this very point. I am sure there is an infinite number of numbers exhibiting this problem, and floating point precision is a problem that plagues any computer programming language with finite representation of floating point numbers - just about everyone there is, considering that the limitation is hardware-related; software developers are perfect. I think there are several implementations in the ML family of PL's that allow for a different handling, and I seem to remember Ruby had something like this, but I imagine you don't care about this

Can you consider acquiring the input data into a string and then performing a simple parsing to determine the number in the "integer" form?

Best regards,
Lucian
__________________
Please read these Guidelines before posting on the forum

"A person who never made a mistake never tried anything new."
Einstein
  #4  
Old 23-Oct-2006, 12:06
JdS's Avatar
JdS JdS is offline
Senior Member
 
Join Date: Aug 2001
Location: KUL, Malaysia
Posts: 3,371
JdS will become famous soon enough

Re: The mystery of 9.95


TurboPT,

Thank you for the suggestion but I didn't notice a change. Just in case I misunderstood you, here's what I edited in the example script.

PHP Code:

<?php
if( isset($_POST['price'])  &&  $_POST['price'] )
{
    $price['dollars'] = floatval( trim($_POST['price']) );
    //$price['cents'] = intval( $price['dollars']*100.0 );
    $price['cents'] = intval( $_POST['price']*100 );
    printf( "<p>\$%s is %d cents.</p>", $price['dollars'], $price['cents'] );
    $form_price_value = &$price['dollars'];
}
else
{
    $form_price_value = null;
}
echo     "<form method=\"post\" action=\"$_SERVER[PHP_SELF]\">"
        .     "<p>Price: <input type=\"text\" name=\"price\" value=\"$form_price_value\" /></p>"
        .     "<p><input type=\"submit\" name=\"submit\" value=\"How much is that in cents?\" /></p>"
        . "</form>"
?>


Lucian,

I read that page actually, but I was just annoyed because I couldn't understand why it was happening randomly. Why would 9.95 turn into 994 but 6.95 works out fine into 695!

Can I just add 0.000001 to the value? You know, as a quick fix?
  #5  
Old 23-Oct-2006, 12:19
LuciWiz's Avatar
LuciWiz LuciWiz is offline
Moderator
 
Join Date: Jul 2004
Location: Cluj-Napoca (Romania)
Posts: 889
LuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the roughLuciWiz is a jewel in the rough

Re: The mystery of 9.95


Quote:
Originally Posted by JdS
Lucian,

I read that page actually, but I was just annoyed because I couldn't understand why it was happening randomly. Why would 9.95 turn into 994 but 6.95 works out fine into 695!

Can I just add 0.000001 to the value? You know, as a quick fix?

No, that wouldn't really be a fix, since you would still perform operations on floating point numbers, and that is prone to rounding errors. I would recommend reading What Every Computer Scientist Should Know About Floating-Point Arithmetic, but I understand you are in a real hurry to solve the problem. I am also sorry for throwing links at you, but I feel like I am really not qualified to explain those things myself, as I find them to be hardly straight-forward. I can tell you that some time ago Intel actually had to recall an entire series of processors which displayed gross rounding errors for floating point numbers, but otherwise they are accepted as a limitation of the current hardware, which only works with base 2 numbers.

Long story short, wouldn't it be easier to just accept the data as a string, e.g:

"12.345"

and parse the string as:

"12"
"345"

than make

"12345"

out of it and convert that to an integer?

You know I don't program in Php
__________________
Please read these Guidelines before posting on the forum

"A person who never made a mistake never tried anything new."
Einstein
  #6  
Old 23-Oct-2006, 12:20
JdS's Avatar
JdS JdS is offline
Senior Member
 
Join Date: Aug 2001
Location: KUL, Malaysia
Posts: 3,371
JdS will become famous soon enough

Re: The mystery of 9.95


Brilliant! Thank you Lucian. Simple, and does the job!
  #7  
Old 23-Oct-2006, 14:02
TurboPT's Avatar
TurboPT TurboPT is offline
Regular Member
 
Join Date: Feb 2006
Location: Atlanta, GA
Posts: 926
TurboPT is a jewel in the roughTurboPT is a jewel in the roughTurboPT is a jewel in the rough

Re: The mystery of 9.95


JdS,
I was thinking more along the lines of: [without using intval()]
PHP Code:

$price['cents'] = $_POST['price']*100; 


That's all, but glad you got it working!
__________________
Use the force...read the source!!
WYCIWYG -- what you code is what you get!
 
 

Recent GIDBlog2nd Week of IA Training by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Search Engine Optimization mystery saxena Search Engine Optimization Forum 2 05-Apr-2006 07:42

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 20:31.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.