Matthew,

You are absolutely right, we have to do something about handling money better before 
anyone else
notices that 0.7 plus 0.1 is not 0.8 with php!  (I've already had an e-commerce user 
notice that
their account balance is misquoted because 82 - 2 became 79 because of this).

Looking through this thread it seems :

1. Floating points are not accurate, floating point arithmetic is not accurate enough 
for money
calculations. 

2. Zeev is worried that a string based type would create performance problems.

3. The standard approach when programming in low-level languages such as C or Java, is 
to convert to
"pennies" and rely on integer arithmetic.

4. bc calculations/comparisons are safe.

5. Something funny is already happening in php with decimals i.e. print 1 * 0.1 is 
always 0.1 and
never 0.10000001 or whatever else has the same binary representation.


My questions are:

1. Is it useful to cut down the "money" problem to the bare esentials? e.g. 
        - only handle addition/subtraction/multiplication 
        - never worry about more than 2 decimal places
        - maximum values could be practically limited to a billion or so

2. Could we use integer arithmetic for money, given the above restrictions?  We only 
have to spot a
"money" field and carry out integer arithmetic rather than floating point arithmetic.  
Of course we
need to multiply the operands by 100 before the addition and divide by 100 at the end. 
 Would that
bring back the floating point problem in a new guise?

3. How does mysql get away with it?  I've never had a smidgeon of trouble with mysql 
adding
decimals.  In fact,  my "safe" fall back for my bug will be to get mysql to do all the 
arithmetic
rather than php.

4. How bad could performance get?  How much non-integer, non-money, floating point 
calculation  is
really done in php code? Apart from some gd stuff, I can't think when I ever actually 
do a
non-integer, non-money calculation!

5. If actual overall impact on php applications is not too bad, (even if we slow 
floating point by a
factor of ten), could we just use bc routines for all floating point?  Perhaps it 
could be a
configuration option, with the default as precise calculation i.e. use bc, and an 
option for "fast"
i.e. non-bc calculation?


Let me say again, if we want to be treated seriously as a credible HIGH LEVEL 
language, let alone a
reliable e-commerce platform it is NOT ACCEPTABLE that (int) 10 * 0.7 + 0.1 is 7.  It 
doesn't matter
how much documentation we create, it's just not on as default behaviour. So we have to 
do something!

The alternative is that sooner or later we'll be reading a press release from Seattle 
that runs
something like this...

PHP dangerous for e-commerce
Reports are coming in of serious failings at e-commerce sites using php.  These result 
from
fundamental weaknesses in php's basic arithmetic on monetary figures.  Accounting 
integrity is
acknowledged to be completely compromised if developers rely on default php 
arithmetic.  Even
calculations such as 8.20 - 0.20 are not dependable.  The problems are particularly 
dangerous
because they are intermittent.  Php's development team have been aware of this for 
over a year and
despite their much vaunted "open source rapid response", there is no fix, nor even any 
intention of
a fix to this problem.  Instead they choose to highlight weaknesses in their 
underlying C platform.

Bigsoft CEO, Robert Doorways comments : This totally vindicates our view that Open 
Source
technologies must not be relied upon for professional corporate applications.  Only 
the most
experienced and highly resourced software suppliers have the understanding and 
capability to deliver
to the corporate market.  We fully sympathise with customers who have been taken in by 
the
exaggerated claims of the Open Source movement.  We have set up a special php 
translation facilities
for everyone who wants to convert their php applications to a more stable language.   
At BigSoft we
have been counting our own and especially other people's money from our earliest days, 
and are
specialists in big money calculations...



George

Matthew Hagerty wrote:
> 
> At 12:09 PM 12/5/2001 +0200, Zeev Suraski wrote:
> >At 00:38 05/12/2001, Matthew Hagerty wrote:
> >>Okay, then why when I ask PHP to show me the value of $fFloat1, do I get
> >>this:
> >>
> >>printf("%f", $fFloat1);  -> 63.670000
> >>
> >>Not some long draw out number like 63.67000000001 or even
> >>63.66999999999...  If PHP uses precision past the 6 digit then it needs
> >>to show me that it does.
> >>
> >>I can't agree with your reason because computers are not that imprecise.
> >
> >They are.  Generally, the equality operator on floats is inaccurate by
> >definition, you learn that in Numeric Analysis 101 :)  Comparing floating
> >point numbers should only be done by comparing ranges.  E.g., something like
> >
> >abs($num1-$num2)<0.00001
> 
> Yes, I'm finding this out...  It was my own ignorance that let me shoot my
> mouth off.  I should know better, but frustration set in early.
> 
> <snip>
> >>However, even if the number is not stored as indicated, ie. 3.55000000001
> >>instead of a clean 3.550000000, then why does PHP take the liberty to
> >>chop off that precision when converting to a string?  And why is that
> >>precision not put back on when going back to a double?  It is not put
> >>back on because PHP can represent 3.55 as a clean 3.5500000000, so the
> >>assignment of floats, ie. $fFloat = 3.55;, is coded in error in PHP's
> >>internals!?
> >
> >There's no clean 3.55, there simply isn't.  It's just how computers
> >work.  The only way to do what you're asking for is to switch to a whole
> >different string-based representation, which is going to slow things down
> >very considerably.
> 
> My tests in C revealed that with floats (4 byte floats) the math works, I
> guess the precision can be kept under control, but when using doubles I get
> the same results as I got with the PHP code.
> 
> Why was the decision made to have all "float" types in PHP set to
> doubles?  Doubles are good for really big numbers, but floats come in handy
> at times too (like this) where the added precision becomes more of a
> hindrance.  Any chance in getting both 4-byte floats and 8-byte doubles
> into PHP?
> 
> The issue that kicked this whole thing off came about because I have to
> deal with money values.  PHP only has integers and doubles for dealing with
> numbers, not counting boolean (unless I missed one), so you can't really
> reliably represent, say $3.55.  Money math is a tricky beast and values
> need to be kept under control.  It would be nice to have a fixed precision
> type similar to SQL's numeric or number types.  I can get by with bcmath
> for now, but a built-in type that takes care of this kind of thing
> automatically would be really nice!
> 
> >It was annoying to discover this reality for me as well when I took this
> >course a few years ago, but it's reality all the same.  You can search the
> >Web for this issue, e.g.
> >http://www.google.com/search?q=%22never+compare%22+%22floating+point+numbers%22
> >
> >Zeev
> 
> Thanks for the education, sorry about all the fussing!
> 
> Matthew

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to