• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Is this a bug, or am I?

 
Dave Harpster
Greenhorn
Posts: 7
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 18671
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Dave Harpster
Greenhorn
Posts: 7
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thanks
 
Ilja Preuss
author
Sheriff
Posts: 14112
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Thomas Paul
mister krabs
Ranch Hand
Posts: 13974
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic