By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,851 Members | 1,022 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,851 IT Pros & Developers. It's quick & easy.

Check my math!

P: n/a
Someone please explain what alternate universe I fell into this
afternoon when PHP started telling me that 2 doesn't equal 2.

Not sure about you, but when I run this, it tells me 59001.31 doesn't
equal 59001.31. Change each side of the equation by a hundreth or two
and it checks. Change it a bit more, and it won't.

_What_ is going on here?!

<?php
$subtotal=59001.31;
$principal=58605.33;
$interest=395.98;
$check=$principal+$interest;
echo("<pre>");
echo("Check: " . $check . "\n");
echo("Subtotal: " . $subtotal . "\n");
if($check!=$subtotal) {
echo("Check (" . $check . ") does not equal subtotal (" .
$subtotal . ")"); // Check doesn't equal subtotal
}
else {
echo("Check (" . $check . ") equals subtotal (" . $subtotal .
")"); // Check does equal subtotal
}
echo("</pre>");
?>

--
Craig Bailey, Communications Coordinator
Vermont Housing Finance Agency (VHFA)
164 St. Paul St., P.O. Box 408
Burlington, Vt. 05402-0408
Email: cb*****@vhfa.org | Web: www.vhfa.org
Phone: (802) 652-3463 | Fax: (802) 864-5746
Jul 17 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a
Floating operations always introduces small errors, that's why. Run this and
you'll see:

<?php
$subtotal=59001.31;
$principal=58605.33;
$interest=395.98;
$check=$principal+$interest;
$diff=$check - $subtotal;
echo("<pre>");
echo("Check: " . $check . "\n");
echo("Subtotal: " . $subtotal . "\n");
if($check!=$subtotal) {
echo("Check (" . $check . ") does not equal subtotal (" .
$subtotal . ")."); // Check doesn't equal subtotal
printf("Their difference is %01.40f", $diff);
}
else {
echo("Check (" . $check . ") equals subtotal (" . $subtotal .
")"); // Check does equal subtotal
}
echo("</pre>");
?>

The decimal part of a float is represented internally as a fraction of some
denominator that is of the power of 2. Decimals that are not
1/(2^n)therefore cannot be represented precisely.

59001.31 is 59001 + 5325759447 / 2^34 or
59001.3099999999976716935634613037109375
58605.33 is 58605 + 22677427323 / 2^36 or
58605.330000000001746229827404022216796875
395.98 is 395 + 2155042790441 / 2^41 or
395.9800000000000181898940354585647583007813

When you add up the fractions, lo and behold, they don't add up exactly (the
error is 1/(2^37)).

You should do what Mike suggested. Whenever you divide something or multiple
something by a floating point number, pass the result through round().

Uzytkownik "Craig Bailey" <cb*****@vhfa.org> napisal w wiadomosci
news:cb***************************@sover.net.clien t.newsread.com...
Someone please explain what alternate universe I fell into this
afternoon when PHP started telling me that 2 doesn't equal 2.

Not sure about you, but when I run this, it tells me 59001.31 doesn't
equal 59001.31. Change each side of the equation by a hundreth or two
and it checks. Change it a bit more, and it won't.

_What_ is going on here?!

<?php
$subtotal=59001.31;
$principal=58605.33;
$interest=395.98;
$check=$principal+$interest;
echo("<pre>");
echo("Check: " . $check . "\n");
echo("Subtotal: " . $subtotal . "\n");
if($check!=$subtotal) {
echo("Check (" . $check . ") does not equal subtotal (" .
$subtotal . ")"); // Check doesn't equal subtotal
}
else {
echo("Check (" . $check . ") equals subtotal (" . $subtotal .
")"); // Check does equal subtotal
}
echo("</pre>");
?>

--
Craig Bailey, Communications Coordinator
Vermont Housing Finance Agency (VHFA)
164 St. Paul St., P.O. Box 408
Burlington, Vt. 05402-0408
Email: cb*****@vhfa.org | Web: www.vhfa.org
Phone: (802) 652-3463 | Fax: (802) 864-5746

Jul 17 '05 #2

P: n/a

"Chung Leong" <ch***********@hotmail.com> wrote
You should do what Mike suggested. Whenever you divide something or multiple something by a floating point number, pass the result through round().


LOL somebody here capable of programming? Just ironic, reading too much
bulls*** here.

What should somebody use floats for, when always rounding that shit before
doing mathematics?

If you have to use floats and need to to compare them, round them before
comparing. But when using floats that have to be compared, your concept is
broken.

Carl
Jul 17 '05 #3

P: n/a
In article <2O*****************@newssvr27.news.prodigy.com> ,
"CountScubula" <me@scantek.hotmail.com> wrote:
I did not get into it, but just for a quick reference, when you deal with
money in software/scripts, it is best to convert over to cents, thus 395.98
is 39598, deal with all numbers as whole numbers, and when you go to print
it then add the decimal, the decimal is a human thing, for parts of a
dollar.


Thanks for all the help. Though I admit that I'm a little floored that a
scripting language doesn't have a more elegant way to handle something
like ... er ... _numbers_.

And here I thought computers were _good_ with numbers ...

--
Craig Bailey, Communications Coordinator
Vermont Housing Finance Agency (VHFA)
164 St. Paul St., P.O. Box 408
Burlington, Vt. 05402-0408
Email: cb*****@vhfa.org | Web: www.vhfa.org
Phone: (802) 652-3463 | Fax: (802) 864-5746
Jul 17 '05 #4

P: n/a
On Tue, 13 Jan 2004 18:20:34 GMT, Craig Bailey <cb*****@vhfa.org> wrote:
In article <2O*****************@newssvr27.news.prodigy.com> ,
"CountScubula" <me@scantek.hotmail.com> wrote:
I did not get into it, but just for a quick reference, when you deal with
money in software/scripts, it is best to convert over to cents, thus 395.98
is 39598, deal with all numbers as whole numbers, and when you go to print
it then add the decimal, the decimal is a human thing, for parts of a
dollar.


Thanks for all the help. Though I admit that I'm a little floored that a
scripting language doesn't have a more elegant way to handle something
like ... er ... _numbers_.

And here I thought computers were _good_ with numbers ...


They are. But there have to be compromises when storing floating point
numbers. For example, if you do 1.0/3.0, you get 0.33333 recurring. How do you
store an infinite number of decimal places in a (small) finite space?

There are floating point storage schemes that can represent recurring numbers
exactly, but they're relatively complicated. The IEEE format used by most
processors lets you store the number in a smallish space and have simpler
circuitry to process it, but the compromise is you lose accuracy after a
certain number of significant digits.

It's a hardware thing, not a language thing.

So, if you want exact maths on a computer, use integers, or find one of the
exact floating point maths libraries and put up with the performance penalties.

--
Andy Hassall <an**@andyh.co.uk> / Space: disk usage analysis tool
<http://www.andyh.co.uk> / <http://www.andyhsoftware.co.uk/space>
Jul 17 '05 #5

P: n/a
CountScubula wrote:
I did not get into it, but just for a quick reference, when you deal with
money in software/scripts, it is best to convert over to cents, thus
395.98 is 39598, deal with all numbers as whole numbers, and when you go
to print it then add the decimal, the decimal is a human thing, for parts
of a dollar.

just my 2 cents or ($.02)

--
Mike Bradley "Craig Bailey" <cb*****@vhfa.org> wrote in message
news:cb***************************@sover.net.clien t.newsread.com...
Someone please explain what alternate universe I fell into this
afternoon when PHP started telling me that 2 doesn't equal 2.

Not sure about you, but when I run this, it tells me 59001.31 doesn't
equal 59001.31. Change each side of the equation by a hundreth or two
and it checks. Change it a bit more, and it won't.

_What_ is going on here?!


Heheh - I remember them telling us that in my 1st year of computer science
:) I so rarely deal with currency stuff I'd almost forgotten! Thanks for
the reminder.

James
--
Fortune cookie says:
America has been discovered before, but it has always been hushed up.
- Oscar Wilde

Jul 17 '05 #6

P: n/a
"CountScubula" <me@scantek.hotmail.com> schrieb im Newsbeitrag
news:2O*****************@newssvr27.news.prodigy.co m...
I did not get into it, but just for a quick reference, when you deal with
money in software/scripts, it is best to convert over to cents, thus 395.98 is 39598, deal with all numbers as whole numbers, and when you go to print
it then add the decimal, the decimal is a human thing, for parts of a
dollar.


So when using signed 32 bit integer values (the only PHP knows) you have
2,000,000,000 Cent or better 20,000,000.00 $ to be the limit of economics.
PHP then starts converting values to FLOAT. So when handling huge values one
better doesn't compare without additional rounding.

Carl
Jul 17 '05 #7

P: n/a
In article <i4********************************@4ax.com>,
Andy Hassall <an**@andyh.co.uk> wrote:
But there have to be compromises when storing floating point
numbers. For example, if you do 1.0/3.0, you get 0.33333 recurring. How do
you
store an infinite number of decimal places in a (small) finite space?


But that's not what I'm doing. I'm doing addition. I'm taking 10.25 and
adding it to 11.4.

Why can't the computer recognize that as 21.65?

If $total=21.65 and I compare that to 10.25+11.4, the fact that the
computer might not be able to recognize a match perplexs me.

I set $total=21.65 and ask it to print $total. It prints 21.65.

I set $anotherTotal=10.25+11.4. I ask it to print $anotherTotal. It
prints 21.65.

_Then_ I ask it if $total equals $anotherTotal and is says "No."

Huh?

--
Floydian Slip(tm) - "Broadcasting from the dark side of the moon"
Random Precision Productions(tm)
67 Union St. #2D, Winooski, Vt. 05404-1948 USA
Sundays, 7-8 pm - Champ 101.3 FM, Colchester; 102.1 FM, Randolph, Vt.
cc*@floydianslip.com - AIM: RandomPrec - www.floydianslip.com
Jul 17 '05 #8

P: n/a
Mike's suggestion was to use fixed point math. Read the post, pal.

Uzytkownik "Carl Melot" <ca*****@linkwave.org> napisal w wiadomosci
news:bu*************@news.t-online.com...
What should somebody use floats for, when always rounding that shit before
doing mathematics?

If you have to use floats and need to to compare them, round them before
comparing. But when using floats that have to be compared, your concept is
broken.

Carl

Jul 17 '05 #9

P: n/a
On Wed, 14 Jan 2004 00:31:57 GMT, Craig Bailey <cc*@floydianslip.com> wrote:
In article <i4********************************@4ax.com>,
Andy Hassall <an**@andyh.co.uk> wrote:
But there have to be compromises when storing floating point
numbers. For example, if you do 1.0/3.0, you get 0.33333 recurring. How do
you
store an infinite number of decimal places in a (small) finite space?


But that's not what I'm doing. I'm doing addition. I'm taking 10.25 and
adding it to 11.4.

Why can't the computer recognize that as 21.65?

If $total=21.65 and I compare that to 10.25+11.4, the fact that the
computer might not be able to recognize a match perplexs me.

I set $total=21.65 and ask it to print $total. It prints 21.65.

I set $anotherTotal=10.25+11.4. I ask it to print $anotherTotal. It
prints 21.65.

_Then_ I ask it if $total equals $anotherTotal and is says "No."


For really gory details into Why, search for 'IEEE floating point
representation'. For example:

http://www.math.grin.edu/~stone/cour...EEE-reals.html

Since the system is based on binary powers, the inaccuracies don't come in
places that you might think if you're thinking in decimal. Various floating
point numbers that have an exact decimal representation end up as recurring
binary representation in the IEEE scheme, so get approximated. Taking the
numbers you pointed out:

<pre>
<?php
$x = 10.25;
$y = 11.4;

printf("x = %10.32f\n", $x);
printf("y = %10.32f\n", $y);
printf("x + y = %10.32f\n", $x+$y);
?>
</pre>

Outputs:

x = 10.25000000000000000000000000000000
y = 11.40000000000000035527136788005009
x + y = 21.64999999999999857891452847979963

I really can't remember the exact details of the IEEE representation any more,
I think like most people I just accept there are inaccuracies and so you
arrange code to expect them, and to minimise the number of repeated operations
(the more you do, the more inaccurate you get).

But from the above, you can see that 10.25 can be exactly represented, but
whilst it's got pretty close to 11.4, it's very slightly off. And again with
the sum of the two, it's slightly off.

With the IEEE representation, there is a (very small) value 'epsilon' which is
a limit of the inaccuracy between the number you want and the stored
representation of it. Check Google, and computer architecture books for the
boring but useful explanation of how it works.

--
Andy Hassall <an**@andyh.co.uk> / Space: disk usage analysis tool
<http://www.andyh.co.uk> / <http://www.andyhsoftware.co.uk/space>
Jul 17 '05 #10

P: n/a
Craig Bailey wrote:
I set $total=21.65 and ask it to print $total. It prints 21.65.

I set $anotherTotal=10.25+11.4. I ask it to print $anotherTotal. It
prints 21.65.

_Then_ I ask it if $total equals $anotherTotal and is says "No."

Huh?


The _internal_ representation of floating-point numbers is not precise!

Try this:

<?php
printf(" %2.8f\n %2.8f\n %2.8f\n\n", 10.25, 11.4, 21.65);
printf("%2.22f\n%2.22f\n%2.22f\n", 10.25, 11.4, 21.65);
?>
--
--= my mail box only accepts =--
--= Content-Type: text/plain =--
--= Size below 10001 bytes =--
Jul 17 '05 #11

P: n/a
On Tue, 13 Jan 2004 18:20:34 +0000, Craig Bailey wrote:
Thanks for all the help. Though I admit that I'm a little floored
that a scripting language doesn't have a more elegant way to handle
something like ... er ... _numbers_. And here I thought computers were _good_ with numbers ...


This only shows how ignorant you are about computers.

Ed
Jul 17 '05 #12

P: n/a
In article <pa****************************@shaw.ca>,
Ed Seedhouse <es********@shaw.ca> wrote:
On Tue, 13 Jan 2004 18:20:34 +0000, Craig Bailey wrote:
Thanks for all the help. Though I admit that I'm a little floored
that a scripting language doesn't have a more elegant way to handle
something like ... er ... _numbers_.

And here I thought computers were _good_ with numbers ...


This only shows how ignorant you are about computers.

Ed


Me ignorant. You arrogant. All comes out in the wash, I guess.

--
Floydian Slip(tm) - "Broadcasting from the dark side of the moon"
Random Precision Productions(tm)
67 Union St. #2D, Winooski, Vt. 05404-1948 USA
Sundays, 7-8 pm - Champ 101.3 FM, Colchester; 102.1 FM, Randolph, Vt.
cc*@floydianslip.com - AIM: RandomPrec - www.floydianslip.com
Jul 17 '05 #13

P: n/a
Craig Bailey wrote:

In article <pa****************************@shaw.ca>,
Ed Seedhouse <es********@shaw.ca> wrote:
On Tue, 13 Jan 2004 18:20:34 +0000, Craig Bailey wrote:
Thanks for all the help. Though I admit that I'm a little floored
that a scripting language doesn't have a more elegant way to handle
something like ... er ... _numbers_.

And here I thought computers were _good_ with numbers ...


This only shows how ignorant you are about computers.

Ed


Me ignorant. You arrogant. All comes out in the wash, I guess.


If you're programming you really should understand this problem. It's very
basic. That's not a dig or anything, just a suggestion on how to further your
skills. The following page explains it pretty well, I think. (sorry if link
doesn't make it under 80 character cut-off.)

http://oopweb.com/Assembly/Documents...14/CH14-1.html

Regards,
Shawn
--
Shawn Wilson
sh***@glassgiant.com
http://www.glassgiant.com

I have a spam filter. Please include "PHP" in the
subject line to ensure I'll get your message.
Jul 17 '05 #14

P: n/a
Craig Bailey wrote:

In article <pa****************************@shaw.ca>,
Ed Seedhouse <es********@shaw.ca> wrote:
On Tue, 13 Jan 2004 18:20:34 +0000, Craig Bailey wrote:
Thanks for all the help. Though I admit that I'm a little floored
that a scripting language doesn't have a more elegant way to handle
something like ... er ... _numbers_.

And here I thought computers were _good_ with numbers ...


This only shows how ignorant you are about computers.

Ed


Me ignorant. You arrogant. All comes out in the wash, I guess.


Or read the "Floating point precision" box in the following:

http://ca.php.net/manual/en/language....float.casting

Regards,
Shawn
--
Shawn Wilson
sh***@glassgiant.com
http://www.glassgiant.com

I have a spam filter. Please include "PHP" in the
subject line to ensure I'll get your message.
Jul 17 '05 #15

P: n/a
On Wed, 14 Jan 2004 10:12:54 -0400, Shawn Wilson
<sh***@glassgiant.com> brought forth from the murky depths:
http://oopweb.com/Assembly/Documents...14/CH14-1.html


All chars came through, 404 error anyway, Shawn, both in NN7 and IE6.
Not Found
The requested URL /Assembly/VolumeFrames.html was not found on this
server.

Additionally, a 404 Not Found error was encountered while trying to
use an ErrorDocument to handle the request.

--------------------------------------------------------------------------------

Apache/1.3.29 Server at www.oopweb.com Port 80

----------------------------------
VIRTUE...is its own punishment
http://www.diversify.com Website Applications
==================================================
Jul 17 '05 #16

P: n/a
Larry Jaques wrote:

On Wed, 14 Jan 2004 10:12:54 -0400, Shawn Wilson
<sh***@glassgiant.com> brought forth from the murky depths:
http://oopweb.com/Assembly/Documents...14/CH14-1.html


All chars came through, 404 error anyway, Shawn, both in NN7 and IE6.

Not Found
The requested URL /Assembly/VolumeFrames.html was not found on this
server.

Additionally, a 404 Not Found error was encountered while trying to
use an ErrorDocument to handle the request.


Weird. It works fine in NS 4.75 (just checked it again, not from cache).
Anyway, the php.net link should work...

Regards,
Shawn
--
Shawn Wilson
sh***@glassgiant.com
http://www.glassgiant.com

I have a spam filter. Please include "PHP" in the
subject line to ensure I'll get your message.
Jul 17 '05 #17

P: n/a
On Wed, 14 Jan 2004 11:08:13 -0400, Shawn Wilson
<sh***@glassgiant.com> brought forth from the murky depths:
Larry Jaques wrote:

On Wed, 14 Jan 2004 10:12:54 -0400, Shawn Wilson
<sh***@glassgiant.com> brought forth from the murky depths:
>http://oopweb.com/Assembly/Documents...14/CH14-1.html


All chars came through, 404 error anyway, Shawn, both in NN7 and IE6.

Not Found
The requested URL /Assembly/VolumeFrames.html was not found on this
server.

Additionally, a 404 Not Found error was encountered while trying to
use an ErrorDocument to handle the request.


Weird. It works fine in NS 4.75 (just checked it again, not from cache).
Anyway, the php.net link should work...


I'll review both, thanks.

I hit the root domain, followed the links, and it worked. Evidently
it needed the stupid HTML frames to be set up from another page. But
what do programmers know about web design? <g>
----------------------------------
VIRTUE...is its own punishment
http://www.diversify.com Website Applications
==================================================
Jul 17 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.