Velocity Reviews > Java > double add problem

Joe Pribele
Guest
Posts: n/a

 07-30-2003
When I add these two numbers together I get a number that is off by very
small amount is this because double is a floating point.
This may not seem like much but when I add on couple more numbers and
then round I am off by 1 which is alot.

java
20.5114 + 1.5890000000000002 = 22.100399999999997 // not quite right

windows calculator
20.5114 + 1.5890000000000002 = 22.1004000000000002 // this is correct

public class test {
public static void main(String[] args ) {
System.out.println( 20.5114 + 1.5890000000000002 );
}
}

Marco Schmidt
Guest
Posts: n/a

 07-30-2003
Joe Pribele:

>When I add these two numbers together I get a number that is off by very
>small amount is this because double is a floating point.

Yes, floating point types by their very nature are inexact.

Check out Roedy's Java glossary or just ask Google, there are some
introductory texts on the topic.

Regards,
Marco
--
Java programming tips: http://jiu.sourceforge.net/javatips.html
Other Java pages: http://www.geocities.com/marcoschmidt.geo/java.html

Mark Thornton
Guest
Posts: n/a

 07-30-2003
Joe Pribele wrote:
> When I add these two numbers together I get a number that is off by very
> small amount is this because double is a floating point.
> This may not seem like much but when I add on couple more numbers and
> then round I am off by 1 which is alot.
>
> java
> 20.5114 + 1.5890000000000002 = 22.100399999999997 // not quite right
>
> windows calculator
> 20.5114 + 1.5890000000000002 = 22.1004000000000002 // this is correct
>
> public class test {
> public static void main(String[] args ) {
> System.out.println( 20.5114 + 1.5890000000000002 );
> }
> }
>

It seems that the current (Windows XP) version of calculator isn't using
doubles for calculation. It can produce values like
22.0004000000000001001000001, which has far more precision than a
double. If you want to do this in Java, use the java.math.BigDecimal
class. This is much slower than double, but will behave as expected.
Floating point arithmetic is faster, but more complex to understand and
use correctly.

Mark Thornton

Tim Slattery
Guest
Posts: n/a

 07-30-2003
Joe Pribele <jpribele@no_spam.bglgroup.com> wrote:

>When I add these two numbers together I get a number that is off by very
>small amount is this because double is a floating point.

Floating point numbers are approximations, there's nothing you can do
about that. If you require a large degree of precision, check out the
BigDecimal class.

--
Tim Slattery
http://www.velocityreviews.com/forums/(E-Mail Removed)

Tor Iver Wilhelmsen
Guest
Posts: n/a

 07-30-2003
Joe Pribele <jpribele@no_spam.bglgroup.com> writes:

> 20.5114 + 1.5890000000000002 = 22.100399999999997 // not quite right

Binary floating point numbers are not 100% accurate.

> 20.5114 + 1.5890000000000002 = 22.1004000000000002 // this is correct

Then approximate the calculator by using java.math.BigDecimal

Joe Pribele
Guest
Posts: n/a

 07-30-2003
In article <MPG.1991ecfc4289d621989680
@nntp.lndn.phub.net.cable.rogers.com>, jpribele@no_spam.bglgroup.com
says...
> When I add these two numbers together I get a number that is off by very
> small amount is this because double is a floating point.
> This may not seem like much but when I add on couple more numbers and
> then round I am off by 1 which is alot.
>
> java
> 20.5114 + 1.5890000000000002 = 22.100399999999997 // not quite right
>
> windows calculator
> 20.5114 + 1.5890000000000002 = 22.1004000000000002 // this is correct
>
> public class test {
> public static void main(String[] args ) {
> System.out.println( 20.5114 + 1.5890000000000002 );
> }
> }
>
>

Thanks every one for the quick response. You confirmed my suspicions.

Joe

Roedy Green
Guest
Posts: n/a

 07-30-2003
On Wed, 30 Jul 2003 19:59:07 GMT, Joe Pribele
<jpribele@no_spam.bglgroup.com> wrote or quoted :

>When I add these two numbers together I get a number that is off by very
>small amount is this because double is a floating point.

see http://mindprod.com/jgloss/floatingpoint.html

--
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.

Tom McGlynn
Guest
Posts: n/a

 07-31-2003
Tor Iver Wilhelmsen wrote:

> Joe Pribele <jpribele@no_spam.bglgroup.com> writes:
>
>
>>20.5114 + 1.5890000000000002 = 22.100399999999997 // not quite right

>
>
> Binary floating point numbers are not 100% accurate.
>
>
>>20.5114 + 1.5890000000000002 = 22.1004000000000002 // this is correct

>
>
> Then approximate the calculator by using java.math.BigDecimal

This subject comes up frequently and I've got some problems with
the typical discussion. It tends to say things that are not
true or at least misleading. This includes Roedy's discussion
in the glossary as well as the first statement in the reply above.
My feeling is this tends to make floating point numbers
more mysterious than they should be.

Binary floating point numbers as used by Java <are>
precise/accurate/exact. They represent a unique point on the real
number line. However the set of available numbers is not dense.
Only an infinitesimally small fraction (literally) of the
points on the number line are included in either of the
floating point representations thatJava uses.

There are two common cases where a Java process needs to choose
which one of these numbers that it can represent should be
used in the place of a number that it cannot. These approximations
are well defined, but give results different from what would
be the case if Java floats/doubles could exactly represent all numbers.

The first is the conversion from finite decimal floating
point numbers. Most numbers which have finite decimal representation
do not have a finite binary representation. E.g., the fraction 3/10 has
a finite decimal floating representation (0.3) but no finite
representation in binary floating point (it's something like
0.010011001100110011...B).

So when a user enters a string "0.3" and asks to convert that string
to a binary floating point number -- at either compile time or during
the execution of the program -- there just isn't any such number
available. The rules state that the closest available number will be
chosen, but in the vast majority of cases there will not be an exact
match. The conversion is well defined, but it is many-one. Many
(indeed an infinity) of real numbers could be converted to each of the
available numbers.

Once Java has numbers in binary, it allows the user to do arithmetic
on them. There are specific rules for how this arithmetic is done.
While these rules try to match what we are familiar with, often
the 'exact' result is a number that is not in the representable
set. E.g., with

double x= 3; double y=10; double z = x/y;

we again have a case where the value that would naively be expected
for z is not in the set of double values that Java supports. Java is
very explicit in specifying exactly which value will be selected, but
it's not quite the same value as one might anticipate. This is
of course what's happened in the example above. The number
22.1004000000000002 is not representable in Java, so it took
the nearest number in the representable set which is something
very close to 22.100399999999997. In fact it probably requires
over 50 digits to represent exactly but Java just writes out
enough digits to distinguish it from any of the other representable
numbers. [All numbers with finite binary representations also have
finite decimal representations, usually with about as many decimal
digits are there are in the binary representation.]

Roedy's Web page implies that all calculations are fuzzy. This is not
the case. If the calculated value is in the set of representable
numbers, the calculation is performed exactly, e.g., for adding,
subtracting or multiplying small integer values.
If not, then the nearest representable value is chosen.
Arithmetic is precisely defined -- there
is almost no room for different machines to chose different values --
but Java gives slightly different results than would be expected if all
real numbers were representable in the set of Java floating point
numbers.

Roedy's page also misleads users in the discussion of the
StrictMath library and the non-strictfp expressions. These have nothing
to do with guard bits in the normal sense of the word.

The StrictMath library is used to give the standard results from the
standard math functions (trig, log, etc). A Java implementation
is allowed to use a Math library which gives very slightly different
(but essentially as accurate) values, that uses a different
algorithm in the computation -- perhaps taking advantage of local
hardware. This has nothing to do with guard bits. I believe in Sun's
JDK's the two actually are the same.

There is also a strictfp qualifier that users can specify for methods
and blocks. Within a strictfp block, all intermediate results
must be in the representable set. However outside of strictfp,
intermediate results may have exponents which are outside the range
of those that are usually permitted. If no intermediate result
would overflow, underflow (or result in denormalized value), then
the strictfp qualifier makes no difference. So, for double precision
as long as the intermediate values have magnitudes between 1.e-300 and
1.e300 (or exactly 0), strictfp makes no difference. However
something like:

double x= 1.e-200;
x = x*x/x;

must return 0 in a strictfp expression: since 1.e-400 is smaller than
the smallest representable number it would underflow to 0. In a
non-strictfp expression, it is allowed to return 1.e-200 (but not
required to).

While strictfp and StrictMath address quite distinct issues,
the overwhelming majority of users can completely
ignore the existence of both.

This isn't meant as a criticism of Roedy or the other posters. However
I think that in trying to simplify the discussion there's a tendency to
use language that makes it hard to understand how floating point
numbers really work and make it seem like floating point arithmetic
isn't well defined.

Tom

Roedy Green
Guest
Posts: n/a

 08-04-2003
On Thu, 31 Jul 2003 13:42:50 -0400, Tom McGlynn
<(E-Mail Removed)> wrote or quoted :

>Binary floating point numbers as used by Java <are>
>precise/accurate/exact.

That is a philosophical point. What does it mean to say an "number"
is accurate? It means "does it reflect the value it stands for?"

Ints can get values bang on. doubles often cannot.

Further, I don't believe the results of floating point operations are
guaranteed to be precisely correct to the bit -- e.g. presuming
infinite accuracy, then rounded.

Newbies are the ones puzzled by this. I think it easiest to explain
that floating point always has some fuzz. When they get older they
can learn the full truth.

--
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.

Dale King
Guest
Posts: n/a

 08-04-2003
"Roedy Green" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On Thu, 31 Jul 2003 13:42:50 -0400, Tom McGlynn
> <(E-Mail Removed)> wrote or quoted :
>
> >Binary floating point numbers as used by Java <are>
> >precise/accurate/exact.

>
> That is a philosophical point. What does it mean to say an "number"
> is accurate? It means "does it reflect the value it stands for?"

And floating point fits that defintion. There are a precise finite subset of
the real numbers that are represented in floating point and the encodings of
those values do reflect the values they stand for.

> Ints can get values bang on. doubles often cannot.

That is not true. Ints can only get integers, just as doubles can only get
certain values. Both pick some finite subset of the set of real numbers. The
only difference is that the set chosen for floating point are not evenly
spaced. The distribution is more concentrated around zero and more sparse as
the values get larger. There is nothing imprecise about the operations.

> Further, I don't believe the results of floating point operations are
> guaranteed to be precisely correct to the bit -- e.g. presuming
> infinite accuracy, then rounded.

They are for each individual operation.

> Newbies are the ones puzzled by this. I think it easiest to explain
> that floating point always has some fuzz. When they get older they
> can learn the full truth.

I disagree. I do not believe in teaching someone a lie only to contradict it
later.

--
Dale King

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post Web learner ASP .Net 3 04-26-2006 05:26 PM The Man With No Name DVD Video 3 02-04-2006 01:45 AM Sydex C++ 12 02-17-2005 06:30 PM Tom Accuosti Firefox 3 09-27-2004 10:02 PM sb C++ 4 02-19-2004 07:39 PM