Re: [PHP] Ok, why is this happening...
On Tue, July 19, 2005 10:26 am, John Nichel said: > There's some freaky math going on there or something. I added a couple > of other echos in to see and for some reason it seems to be losing > single digit value (subtracting, rounding down, I don't know). > > $calculatedGross = $originalNet + ( $originalNet * $commissionPct * 0.01 > ); > > echo ( "Gross : " . (int)$calculatedGross ." = ". $originalNet ." + ( ". > $originalNet ." * ". $commissionPct ." *.01 )\n" ); > > $calculatedNet= $calculatedGross / ( 1 + ( $commissionPct * 0.01 )); > > echo ( "Net : " . (int)$calculatedNet." = " . (int)$calculatedGross . " > / ( 1 + ( " . $commissionPct . " * .01 ) )\n" ); Floating point mathematics is inherently "unreliable" in computers. Consider, for example, 1/3 in decimal notation: 1.33... PHP can only write so many digits down in a 32-bit floating point representation, just as you can only write down so many digits before your hand cramps up or you run out of paper or you get lazy and put "..." on the end. :-) Now, the thing to remember is, the problem won't appear where you expect it to from your experience with DECIMAL numbers all your life because floating point numbers are being stored in a binary/hexidecimal notation. If you are feeling particularly masochistic, you can Google for "floating point internal representation mantissa exponent" and you're gonna find out EXACTLY how those numbers get stored. Set aside a good chunk of time to absorb it all... :-) Even something as simple as: could, in theory, print out something like: 1. and be "correct" as far as Computer Science is concerned. If you need PRECISE mathematics, you should use integer and count pennies instead of dollars -- or even 1/10th of pennies or whatever resolution you need. Of course, every step you take on the right, you can only store 1/10th as large a number of dollars as your maximum amount. But you are starting with 2 billion as your max, so that's a lot of room to play with. If you *need* float numbers and precision out to decimal point N, look into BC_MATH and that new-fangled Math package PHP has for this very reason. You'll still be dealing with this issue, but you'll know your numbers are accurate to the Nth decimal point, and it will be painfully obvious in your code that it is so. [It will also be SLOWER than just plain float numbers.] If you just don't care about the damn penny, but want your code to work, something like: if (1.00 <= $x && $x <= 1.01){ // $x == 1, really } may suffice for your everyday work-a-day computing needs... Though that can also turn into a lot more problems than you think, down the line... Remember 2nd Grade when long division was "tricky"? Yeah, well, computers are a hell of a lot more stupid than 2nd Graders, any day of the week. Note that there *ARE* computer languages where are prefectly happy to work in fractions (Lisp is one such language) because somebody has programmed the algebraic rules of fraction arithmetic into the language: (let ((x 1/3) (y 2/3)) (print (+ x y)) will cheefully and with 100% accuracy print out "1" every single time. [Apologies to Guy Steele if my 10-years-unused Lisp syntax is not spot on.] Lisp stores fractions as 2 integers, not as floating point numbers. [Though of course you can ask it to convert and round off if you like.] You could, if you so desired, whip up a PHP "class fraction {" code-base, or even just store fractions as 2-element arrays (numerator, denominator) and write some procedural functions to work with them. It's not exactly Rocket Science to do that. -- Like Music? http://l-i-e.com/artists.htm -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Ok, why is this happening...
Hi I admit not gone trough all of your code, but mostly this happens when mixing the string concatenation operator (.) with the addition (+) or substraction (-) operator. HTH With kind regards Andy On Tuesday 19 July 2005 19:26, John Nichel wrote: > Chris Boget wrote: > >>Chris Boget wrote: > >> > >> > >>>echo "if( $originalNet != $calculatedNet ) = " . ( (int)$originalNet !== > >>>(int)$calculatedNet ) . "\n"; > >> > >> > >>Change this to echo out what you're comparing... > >>echo "if( ". (int)$originalNet ." != ". (int)$calculatedNet ." ) = " . ( > >>(int)$originalNet !== (int)$calculatedNet ) . "\n"; > >>That'll show what numbers is actually trying to match. > > > > Ok, then that begs the following questions: > > > > If I don't cast any of the values, why do they display as being > > identicle? Additionally, why does every IF check fail in that case? > > There's some freaky math going on there or something. I added a couple > of other echos in to see and for some reason it seems to be losing > single digit value (subtracting, rounding down, I don't know). > > $calculatedGross = $originalNet + ( $originalNet * $commissionPct * 0.01 > ); > > echo ( "Gross : " . (int)$calculatedGross ." = ". $originalNet ." + ( ". > $originalNet ." * ". $commissionPct ." *.01 )\n" ); > > $calculatedNet= $calculatedGross / ( 1 + ( $commissionPct * 0.01 )); > > echo ( "Net : " . (int)$calculatedNet." = " . (int)$calculatedGross . " > / ( 1 + ( " . $commissionPct . " * .01 ) )\n" ); > > -- > John C. Nichel > ÜberGeek > KegWorks.com > 716.856.9675 > [EMAIL PROTECTED] -- Registered Linux User Number 379093 Cockroaches and socialites are the only things that can stay up all night and eat anything. Herb Caen -- -- --BEGIN GEEK CODE BLOCK- Version: 3.1 GAT/O/>E$ d-(---)>+ s:(+)>: a--(-)>? C$(+++) UL>$ P-(+)>++ L+++>$ E---(-)@ W+++>+++$ !N@ o? !K? W--(---) !O !M- V-- PS++(+++) PE--(-) Y+ PGP++(+++) t+(++) 5-- X++ R*(+)@ !tv b-() DI(+) D+(+++) G(+) e>$@ h++(*) r-->++ y--()> -- ---END GEEK CODE BLOCK-- -- Check out these few php utilities that I released under the GPL2 and that are meant for use with a php cli binary: http://www.vlaamse-kern.com/sas/ -- -- pgptzLlv5o2r7.pgp Description: PGP signature
Re: [PHP] Ok, why is this happening...
Chris Boget wrote: Chris Boget wrote: echo "if( $originalNet != $calculatedNet ) = " . ( (int)$originalNet !== (int)$calculatedNet ) . "\n"; Change this to echo out what you're comparing... echo "if( ". (int)$originalNet ." != ". (int)$calculatedNet ." ) = " . ( (int)$originalNet !== (int)$calculatedNet ) . "\n"; That'll show what numbers is actually trying to match. Ok, then that begs the following questions: If I don't cast any of the values, why do they display as being identicle? Additionally, why does every IF check fail in that case? There's some freaky math going on there or something. I added a couple of other echos in to see and for some reason it seems to be losing single digit value (subtracting, rounding down, I don't know). $calculatedGross = $originalNet + ( $originalNet * $commissionPct * 0.01 ); echo ( "Gross : " . (int)$calculatedGross ." = ". $originalNet ." + ( ". $originalNet ." * ". $commissionPct ." *.01 )\n" ); $calculatedNet= $calculatedGross / ( 1 + ( $commissionPct * 0.01 )); echo ( "Net : " . (int)$calculatedNet." = " . (int)$calculatedGross . " / ( 1 + ( " . $commissionPct . " * .01 ) )\n" ); -- John C. Nichel ÜberGeek KegWorks.com 716.856.9675 [EMAIL PROTECTED] -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Ok, why is this happening...
> Chris Boget wrote: > > > echo "if( $originalNet != $calculatedNet ) = " . ( (int)$originalNet !== > > (int)$calculatedNet ) . "\n"; > > Change this to echo out what you're comparing... > echo "if( ". (int)$originalNet ." != ". (int)$calculatedNet ." ) = " . ( > (int)$originalNet !== (int)$calculatedNet ) . "\n"; > That'll show what numbers is actually trying to match. Ok, then that begs the following questions: If I don't cast any of the values, why do they display as being identicle? Additionally, why does every IF check fail in that case? thnx, Chris -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP] Ok, why is this happening...
Chris Boget wrote: echo "if( $originalNet != $calculatedNet ) = " . ( (int)$originalNet !== (int)$calculatedNet ) . "\n"; Change this to echo out what you're comparing... echo "if( ". (int)$originalNet ." != ". (int)$calculatedNet ." ) = " . ( (int)$originalNet !== (int)$calculatedNet ) . "\n"; That'll show what numbers is actually trying to match. -- John C. Nichel ÜberGeek KegWorks.com 716.856.9675 [EMAIL PROTECTED] -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php