Solved

Precision of double type variable causing weird decimal issues.

Posted on 2004-08-11
16
217 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 350 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
Revamp Your Training Process

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action.

 
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 150 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

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
arguments to jar 5 40
Java: How do I open the default windows program for a given file type 3 53
how to debug htl and js pages 8 58
java mysql insert application 14 47
Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to implement Singleton Design Pattern in Java.
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

726 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