Solved

Precision of double type variable causing weird decimal issues.

Posted on 2004-08-11
16
212 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
  • 5
  • 3
  • 3
  • +4
16 Comments
 
LVL 92

Expert Comment

by:objects
Comment Utility
Thats the nature of floating point numbers
0
 
LVL 92

Accepted Solution

by:
objects earned 350 total points
Comment Utility
0
 
LVL 1

Expert Comment

by:justywong
Comment Utility
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
 
LVL 92

Expert Comment

by:objects
Comment Utility
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:mayankeagle
Comment Utility
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
Comment Utility
BigDecimal is no solution.
Consider to store       PI      or     E        "exact" .............
;JOOP!
0
 
LVL 2

Author Comment

by:incongruent
Comment Utility
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:mayankeagle
Comment Utility
>> changing all my double types to float

That'll never help. In fact, double is a more stable type than float.
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 30

Expert Comment

by:mayankeagle
Comment Utility
0
 
LVL 16

Assisted Solution

by:imladris
imladris earned 150 total points
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
>  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
Comment Utility
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
Comment Utility
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
Comment Utility
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
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…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:

772 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now