Rasmus, You're right someone doesn't get it, but I'm still not convinced that it's me!!
I do understand that "0.1 cannot be finitely expressed in binary" and in particular that "You can't compare floating points in C". But I don't want to do this! I want to compare php numbers, which can be either strings or floats, in php! This already works fine when the php number is "passed" as a string, I just want it to also work when it's passed as a float/double! I can already do this by an explicit cast to string or call to sprintf on any double float arguments. A string cast magically makes all the problems disappear, #6220, Pierre's and mine: floor((0.7 + 0.1) * 10) ==> 7 floor(''. ((0.7 + 0.1) * 10) ==> 8 floor((string) ((0.7 + 0.1) * 10)) ==> 8 floor(sprintf("%.14f",(0.7 + 0.1) *10)) ==> 8 (Similarily, 63.67 == (string) (3.55 + 60.12) and floor(string(8.2 - 0.2)) == 8.) My understanding, and I'm expecting to be corrected, is that this will always work. Why? Because the string cast is to no more than the number of decimal places (14 or so depending on platform) to which double floating point basic arithmetic is genuinely correct. So it ends up (to this precision), as functionally identical to the recommended C technique of "compare floats within a range". So why doesn't php do this cast/round for me? That's my question. 1. How hard or slow can it be? It's already being done on all the string/output functions, not only string() but the concatenation operator, plain prints etc. etc. To do the same on the integer/boolean returning functions/operators, such as floor(), int(), ==, ===, >= etc. can't be too bad, can it? 2. What harm can it do? Remember, I am not asking for this on the float-returning functions/operators where I would much rather you kept all the extra precision of the full double to stop accumulation of rounding errors. And we are not jeopardising any meaningful results that floor() and co. are already producing on the un-rounded 40 or so decimal digit doubles that we are passing through at the moment, since, as we all know, "you can't compare floats...." 3. Who will be surprised? We are already telling everyone that we're only accurate to 14 or so places on doubles, and that they should use bc, gmp if they want more precision. All the users are accustomed to getting floats back to only this precision, it's only sprintf users who ever have a chance to see the "raw" internal double. I can't imagine anyone being anything but pleasantly surprised to see 0.7 + 0.1 == 0.8 4. Why not just use the workaround? I'll be damned if I do an explicit string cast when php could do it for me! I've grown used to treating strings and numbers interchangeably and I see no reason to change. I also flatly refuse to have to explain to anyone why 0.7 + 0.1 is not 0.8 in php! What have I missed? George "php is much better than you think!" Rasmus Lerdorf wrote: > > I guess you didn't understand any of the explanations you got to this. > #6220 is not a bug. Computers can not represent floating point values > accurately, only to a certain level of precision. Ergo there is no such > thing as precisely 0.1 and any function, such as floor(), which relies on > a number being precisely greater than some floating point number is never > going to work without a little help from the programmer. Bug #6220 is at > best a documentation issue. PHP could not possibly do anything to > accurately guess the intention of the programmer when it comes to this. > You, as a programmer, will have to add the appropriate fuzz factor when > using functions such as floor(), ceil() and round(). > > -Rasmus > > On Fri, 7 Dec 2001, George Whiffen wrote: > > > Pierre/Rasmus/Zeev, > > > > After a little more thought, it seems to me that, my problem, Bug 6220 and >Matthew's original > > problem at the start of this thread are all REAL LIVE BUGS. As Pierre suggested, >php seems to > > handle floating points fine 99% of the time with in its documented precision (14 >decimal digits or > > so depending on platform). This is perfectly suitable for nearly any kind of >money, there's no > > problem there. > > > > The real problem is that floor, int, and the comparisons are going beyond this >precision. Explicit > > string casts solve this by forcing the floats back to our guaranteed precision at >which point > > everything works fine! > > > > I can only guess that internally php carries around as much float precision as it >can to maintain > > accuracy on a series of calculations hence > > > > sprintf("%.50f",(0.7 + 0.1) * 10) is 7.9999999999999991118215802998747676610947 > > and > > sprintf("%.50f",3.55 + 60.12) is 63.6699999999999945998752082232385873794556 > > > > Comparison of these floats with 8 and 63.67 respectively fails at this level of >precision but is > > fine at 14/15 digits. > > > > I can see why php would want to carry the extra precision around through >calculations but not when > > the float is going in as the argument of an integer returning function/operator >such as floor(), > > int(), == or ===. In these cases I take it as a straightforward bug to use more >precision than we > > are supposed to be offering. If someone really wants 32 digit precision on >comparisons, int, floor > > etc. it should be up to them to go off and explicitly ask for bccomp rather than >leaving the likes > > of me to wonder how to explain that 8.2 minus 0.2 is not 8. > > > > Does that sound ok, or am I exhibiting even more ignorance... > > > > Unfortunately for me, the one thing I am fairly sure of, is that mysql is >completely up the spout!!! > > SELECT IF(0.8 = 0.6 + 0.2,'good database','bad database'); > > returns 'bad database' even if you replace the constants with explicit decimal >fields. > > > > So many, many apologies and much grovelling for ever suggesting that msyql managed >to get it right > > while you didn't! Can we re-open 6220 as a bug and attach int, == and === to any >solution? > > > > Chastened, > > > > George > > > > Pierre-Alain Joye wrote: > > > > > > On Thu, 06 Dec 2001 18:03:23 +0000 > > > George Whiffen <[EMAIL PROTECTED]> wrote: > > > > > > > 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. > > > Wrong, It is fully useable for money. But not for mid-hi precision, use BCmath. > > > > > > > 2. Zeev is worried that a string based type would create performance problems. > > > Don't need to convert to string (huh php don't take really care about type). > > > > > > > 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. > > > Sure, best way and solve the round problem, I never used more than 5 digits for >the floating part of a number for money numbers (bank rates and stock calculation). > > > > > > > 4. bc calculations/comparisons are safe. > > > Sure :) > > > > > > > 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 > > > five is sometimes a must 3 needed especially with euro convertion. > > > > > > > - maximum values could be practically limited to a billion or so > > > As explained in the documentation or type ranges. > > > > > > > 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? > > > Sure it does. This tip were usefull in the past with old rdms systems and >improbe indexes with actual system (as far you need indexes on amounts). > > > > > > > 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. > > > Mysql does not any calculation except when you use function and/or operator. > > > Try this : > > > select 1.0120000000000001/1 > > > and then > > > select 1.01200000000000001/1 > > > > > > Damned 2nd one failed... > > > > > > > 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! > > > If high precision floating numbers is your need use bcmath or develop your own >php modules using a dedicated langage or libraries. Float numbers are not finites. >See the last Zeev post for the link about explanations. > > > > > > > 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? > > > You don't slow down your app. Integer process are generally faster (both in >rdbms and cpu). > > > Except if you have a P4 and you use the Intel Compiler... ;)) > > > > > > > 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! > > > Damned ......... > > > > > > > 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... > > > OK but php is fully Y2K compliant ;)). > > > > > > hth > > > > > > pa > > > -- > > > Pierre-Alain Joye > > > Freelance > > > Developpements et Services web/intranet > > > [EMAIL PROTECTED] > > -- 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]