?
Solved

Precision of double type variable causing weird decimal issues.

Posted on 2004-08-11
16
Medium Priority
?
220 Views
Last Modified: 2012-05-05
-JDK VERSION 1.3.1_03
-WIN2000 OS


OK,

I have a custom class that has a double variable.  The class also has a method to add another object of the same class to itself (by adding the double variables and storing the result in the calling object's variable).  For each of the following numbers (below example),  the class is created, the number is set for the field, and then stored in the hashtable.  Each subsequent time the object is stored, it is removed from the hashtable,  the add method is called on the stored object, and then put back into the hashtable.   The problem is that when these objects later used to create a new ArrayList by calling the Hashtable.values() method the sum of these numbers has an additional 0.0000000000002.   I iterate through the arraylist and call the .getDoubleVariable() method for each object.  Oddly enough, I get the following value: 1244.8000000000002 (the ArrayList index would only have 1 entry in this example).

Example:

AnObject o= new AnObject();
o.setDoubleVariable(*x*);
o2=(AnObject)hashtable.get("theobject");
o2.addObjectToThisInstance(o);
hashtable.put("theobject", o2);

number list:
169.8
1075.0
-100.0
100.0
107.5
10.8
20.0
10.75
10.0
10.75
-169.8
-1075.0
1075.0
1075.0
-1075.0


Can anyone explain to me why this is happening?   The answer I expect is 1244.80.  It seems odd that it would throw in such a small decimal value somewhere.  This is a pain since it obviously is not giving me the value I expect.

-Incongruent <|>
0
Comment
Question by:incongruent
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
  • +4
16 Comments
 
LVL 92

Expert Comment

by:objects
ID: 11779757
Thats the nature of floating point numbers
0
 
LVL 92

Accepted Solution

by:
objects earned 1050 total points
ID: 11779789
0
 
LVL 1

Expert Comment

by:justywong
ID: 11779913
You should use BigDecimal if u want a precise result.

Here is a simple exmaple :
http://java.sun.com/developer/TechTips/1999/tt0826.html#tip2

API:
http://java.sun.com/j2se/1.4.2/docs/api/java/math/BigDecimal.html

However, the performance of BigDecimal is poor so use it with care!
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 92

Expert Comment

by:objects
ID: 11779934
Why exactly is the result you are getting a problem?
What accuracy do you need for you double precisions?
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 11781344
Floating-point numbers always behave this way. If you have a C compiler, check this out:

float a = 0.7 ;

if ( a < 0.7 )
  printf ( "A is lesser than 0.7" ) ;
else if ( a == 0.7 )
  printf ( "A is equal to 0.7" ) ;
else
  printf ( "A is greater than 0.7" ) ;

The idea is that there are always issues related with precision, type-cast, etc. In this example, consider the 'if' statement: if ( a < 0.7 ) - here, 'a' is a 'float', whereas the '0.7' constant is treated as a 'double', so there is a temporary implicit type-conversion of 'a' and that results in a precision-loss. But this example will print the correct result if you declare 'a' as double (instead of float), OR let it be a float and compare using: if ( a < ((float) 0.7) )

However, Java was a little more strict not to allow this at all. If you write:

float a = 0.7 ;

if ( a < 0.7 )

- the above 'if' statement will probably result in a compilation error saying "Possible loss of precision" because it knows that the LHS ('a') is a float and the RHS of the in-equality (0.7) is a double.

However, in your case, I guess its again a case of precision-related issues which are always there with floating-point and double values.

Read the link that objects posted.
0
 
LVL 24

Expert Comment

by:sciuriware
ID: 11781680
BigDecimal is no solution.
Consider to store       PI      or     E        "exact" .............
;JOOP!
0
 
LVL 2

Author Comment

by:incongruent
ID: 11782824
OK.   well firstly,  I only need a precision of 2 decimals.  In my application I am checking equality with user input that is limited to two digits.  When I compare the user entry with the total stored,  ithey are not equal.    Furthermore,  I don't want to store the value to the database with these extra unrequired decimal values.    

I called the toFloat() method for the variables and the problem went away,  but can this potentially be a problem for the float type also?  I'm thinking of going back through my 150 some odd classes and changing all my double types to float.  


I'm glad that a few have you have given me some verbose responses,  but they sort of boil down to "Thats the way they work".    If someone can include a common way to correct this problem  (2 decimal precision stays as the expected 2 decimal precision),  I would be a little more satisfied.    

Thanks for your help so far...
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 11782945
>> changing all my double types to float

That'll never help. In fact, double is a more stable type than float.
0
 
LVL 30

Expert Comment

by:Mayank S
ID: 11782974
0
 
LVL 16

Assisted Solution

by:imladris
imladris earned 450 total points
ID: 11784302
The standard tactic for dealing with numbers that require precision, that must avoid the vagueries of floating point numbers, is to use a scaled decimal.

In our software, for instance, we do extensive financial calculations. We must have complete control over the results. A scaled integer is one in which you simply *imagine* the decimal point in the correct place. So, for instance, to represent dollars, we use integers in which we commonly agree that the decimal point occurs before the last two digits. So, to represent 1 dollar, we use the number 100 (i.e. the number of pennies). Integer arithmetic behaves in a straightforward predictable manner.

The extra work here is on input and output. For input you must take the placing of the decimal point into account, and possible scale the input as necessary, and for output you usually have to output the number in two pieces and "manually" insert the decimal point. The work here is normally alleviated by having central input and output routines that are responsible for the necessary manipulations.
0
 
LVL 16

Expert Comment

by:imladris
ID: 11784324
P.S. if you need to represent number larger than can be supported in an integer you can, of course use a long in the same manner. If you need even more digits than that (about 18 in a long), *then* I would reach for the BigDecimal kind of solution.
0
 
LVL 3

Expert Comment

by:kumvjuec
ID: 11785871
If precision to 2 places is all u want, why not store 100*myNum as integer.
Or store them as a String :)
0
 
LVL 92

Expert Comment

by:objects
ID: 11788738
>  I only need a precision of 2 decimals.

the example in your question is accurate to 2 decimal places

> I don't want to store the value to the database with these extra unrequired decimal values.

what type are you using in the database?

>  If someone can include a common way to correct this problem  (2 decimal precision stays as
> the expected 2 decimal precision),  I would be a little more satisfied.

Depends exactly why this is causing a problem.
Obvious solution is don't use floating point numbers if you don't like it.

0
 
LVL 16

Expert Comment

by:imladris
ID: 11821776
Did any of those answers help?

If so, it is now time to close and grade this.

If not, please ask a clarifying question.
0
 
LVL 2

Author Comment

by:incongruent
ID: 11822384
objects,  you are credited with 350 points for answering the original question.  I appreciate your selection of a link that was targetted to my audience and answered the question appropriately  (Although I would suggest breifly summarizing a link rather than responding with it).

imladris, you get 150 for the best answer to the secondary question of how to deal with it.  


I suppose if my education had been in core programming rather than systems analysis I would have been told at some point about these problems with double and float type numbers.    (Better to find out now before I start writing those moon landing programs I had planned,  lol)

Thanks again,

-Incongruent
0
 
LVL 92

Expert Comment

by:objects
ID: 11826426
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Viewers will learn about arithmetic and Boolean expressions in Java and the logical operators used to create Boolean expressions. We will cover the symbols used for arithmetic expressions and define each logical operator and how to use them in Boole…
The viewer will learn how to implement Singleton Design Pattern in Java.
Suggested Courses
Course of the Month8 days, 9 hours left to enroll

765 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question