File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Is this a bug, or am I? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Is this a bug, or am I?" Watch "Is this a bug, or am I?" New topic
Author

Is this a bug, or am I?

Dave Harpster
Greenhorn

Joined: Apr 11, 2002
Posts: 7
I know this sounds dumb but I can't figure out what I'm doing wrong. My program kept coming up with incorrect results with certain input, so I simplified it to test a few things:
public static void main (String args[]) {
double numOne = 100.0d;
double numTwo = 4.1d;
double total = numOne * numTwo;
System.out.println(total);
}
This (when I tried it with jdk 1.4 and 1.3) always produced 4.099999994 instead of 410.
It also does the same for 5.1, but not 2.1 and 6.1. Is this a bug or am I misunderstanding something?
thanks,
dave
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
It's normal. Floats and doubles in Java are always subject to roundoff errors like this - it's ultimately because certain fractional numbers cannot be expressed exactly in binary (much like 1/3 cannot be expressed in decimal). This is common to other languages as well, but most other languages tend to automatically round off the last digit when you convert to a string. Java's designers chose not to do this, preferring to display data as exactly as possible - which in most cases makes things worse, oddly enough.
Basically, anytime you want to display a float or double in Java, you should probably use a java.text.DecimalFormat object to clean it up. E.g.

This always prints at least two digits after the decimal, and up to 6 digit if they're nonzero. See the DecimalFormat doc for more info.


"I'm not back." - Bill Harding, Twister
Dave Harpster
Greenhorn

Joined: Apr 11, 2002
Posts: 7
thanks
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Originally posted by Jim Yingst:
it's ultimately because certain fractional numbers cannot be expressed exactly in binary (much like 1/3 cannot be expressed in decimal).

Correct. In the example:
4.1 decimal
= 4*10^0 + 1*10^-1
= 2^2 + 2^-4 + 2^-5 + 2^-8 + 2^-9 + 2^-12 + 2^-13 ...
= 100.0001100110011... binary
As an aside, we wouldn't have any problems with 1/3 in a ternary system:
1/3 = 3^-1
= 0.1 ternary
This is common to other languages as well, but most other languages tend to automatically round off the last digit when you convert to a string.

There are also languages with a more sophisticated number system. For example, Smalltalk is able to represent fractions without loss of precision.
Basically, anytime you want to display a float or double in Java, you should probably use a java.text.DecimalFormat object to clean it up.

Or you could use java.math.BigDecimal, if you need arbitrary precision.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Thomas Paul
mister krabs
Ranch Hand

Joined: May 05, 2000
Posts: 13974
By the way, all this stuff is explained in:
IEEE Standard for Binary Floating-Point Arithmetic. ANSI/IEEE Std. 754-1985. Available from Global Engineering Documents, 15 Inverness Way East, Englewood, Colorado 80112-5704 USA; 800-854-7179.
Java uses the IEEE 754 standard.


Associate Instructor - Hofstra University
Amazon Top 750 reviewer - Blog - Unresolved References - Book Review Blog
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Is this a bug, or am I?