2.010 * 1000 = 2009

T

Timo Nentwig

Can somebody explain why the following code does output 2009 (at least on an
Athlon XP machine, Window/Linux, jdk1.3 and 1.5)?

class Bug
{
        public static void main( final String[] args )
        {
                final double d = 2.010d;
                System.out.println( (long)( d * 1000d) );
        }
}
 
H

hilz

Timo Nentwig said:
Can somebody explain why the following code does output 2009 (at least on an
Athlon XP machine, Window/Linux, jdk1.3 and 1.5)?

class Bug
{
public static void main( final String[] args )
{
final double d = 2.010d;
System.out.println( (long)( d * 1000d) );
}
}

because this is a floating point computation that might give you an answer
such as
2009.9999999999999999999999999
and casting this into a long will result in 2009
 
E

Eric Sosman

Timo said:
Can somebody explain why the following code does output 2009 (at least on an
Athlon XP machine, Window/Linux, jdk1.3 and 1.5)?

class Bug
{
public static void main( final String[] args )
{
final double d = 2.010d;
System.out.println( (long)( d * 1000d) );
}
}

See http://www.mindprod.com/jgloss/floatingpoint.html
with special attention to point 3. (Disclaimer: I do not
endorse or agree with all the opinions on the cited page.
However, it explains your difficulty satisfactorily.)
 
D

Dag Sunde

Timo Nentwig said:
Can somebody explain why the following code does output 2009 (at least on an
Athlon XP machine, Window/Linux, jdk1.3 and 1.5)?

class Bug
{
public static void main( final String[] args )
{
final double d = 2.010d;
System.out.println( (long)( d * 1000d) );
}
}

Because the value 2.010 can't be stored excactly in the finite
number of bits that represent a double datatype.

For that particular value, something like 2.00999999999...99998 is stored

It uses the IEEE standard 754 for binary floating-point:

The IEEE double precision floating point standard representation requires a
64 bit word, which may be represented as numbered from 0 to 63, left to
right. The first bit is the sign bit, S, the next eleven bits are the
exponent bits, 'E', and the final 52 bits are the fraction 'F':
S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
0 1 11 12 63

The value V represented by the word may be determined as follows:
If E=2047 and F is nonzero, then V=NaN ("Not a number")
If E=2047 and F is zero and S is 1, then V=-Infinity
If E=2047 and F is zero and S is 0, then V=Infinity
If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended
to represent the binary number created by prefixing F with an implicit
leading 1 and a binary point.
If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are
"unnormalized" values.
If E=0 and F is zero and S is 1, then V=-0
If E=0 and F is zero and S is 0, then V=0
 
C

Chiron Paixos

This is an extremely basic question and is explained in most any basic
java book, and in most C and C++ (and probably FORTRAN, BASIC, etc.)
books, too. It is specifically mentioned in the java specs and Sun's
java tutorial.

The answer is that e.g. 0.1 and 0.01 are not an exact values in base
2; they are repeating binary numbers. Thus, when you use either one,
there will be rounding issues. Java tries very hard to get the number
you want, but there's a limit to what you can do. Thus, if you ask

if (0.06 == (0.01 + 0.01 + 0.01 + 0.01 + 0.01 + 0.01) )
{
//do something
}

you would find that the inner code would not execute, because rounding
errors make the if-clause evaluate to false.

When you ask java to convert a double to a String, it does the best it
can, but sometimes things do not round the way you'd like them to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top