float, doubleÀÇ Ç¥Çö, ¿¬»ê ¿ÀÂ÷ ¹× BigDecimal Ŭ·¡½º¸¦ ÀÌ¿ëÇÑ Á¤È®ÇÑ ½ÊÁø¼ö Ç¥Çö ¹× ¿¬»ê


[ Follow Ups ] [ Post Followup ] [ ÀÚ¹Ù ¹¯°í ´äÇϱâ ]

Posted by ±è´öÅ on December 11, 1997 at 02:52:58:

J C Oterhals wrote:
>
> I want to add these numbers together:
>
> 0.1 + 0.5 + 0.4 + 7.1 + 0.1 + 31.6 + 13.3
>
> My calculator tells me that the sum is 53.1, but when adding these
> doubles together, my Java app tells me the sum is 53.100000485777855.
> Am I missing something fundamental here?


floats and doubles are represented internally in radix 2 accodring to IEEE 754-1985 stndard.
So, some of above double constants in radix 10 is converted to numbers in radix 2
when compiling which cause the tiny conversion error.


For example, 0.1 = 2**-4 + 2**-5 + 2**-8 + 2**-9 + 2**-13 + ................ (endless)
The simply looking 0.1 cannot be represented in finite number of radix 2 digits,
so conversion errors necessarily occur in compiled Java programs.


float and doubles and their arithmetic operations (+, -, *, /, ...)
are based on approximation in nature. So, normally this should not cause trouble.
But, applications like calculator should not botther users by such non-intuitive
calculation results.


The solution is to use BigDecimal class in Java 1.1 which provide exact arithmetic
operations and exact internal representation of radix 10 numbers.


You may suspect that this can cause performance degrade.
But, it will not be too slow since calculation-intensive methods are
native methods.


Followings are the sample program and its output which help your understanding.



import java.math.BigDecimal;


class BigDecimalTest
{ public static void main (String[] args)
{
System.out.println( 0.1 + 1.6 );
System.out.println( new BigDecimal(0.1) );
System.out.println( new BigDecimal(1.6) );


// Not soution: 0.1 and 1.6 has already internal representation errors.
System.out.println( new BigDecimal(0.1)
.add( new BigDecimal(1.6) ) );


// Solution 1
System.out.println( new BigDecimal("0.1")
.add( new BigDecimal("1.6") ) );


// Solution 2
System.out.println( BigDecimal.valueOf(1, 1)
.add( BigDecimal.valueOf(16, 1) ) );
}
}


1.7000000000000002
0.1000000000000000055511151231257827021181583404541015625
1.600000000000000088817841970012523233890533447265625
1.7000000000000000943689570931383059360086917877197265625
1.7
1.7


--
Deogtae Kim
CA Lab. CS Dept. KAIST
http://calab.kaist.ac.kr/~dtkim
Sun Certified Java Programmer 1.1



Follow Ups:



À̾ ±Û¿Ã¸®±â(´äÇϱâ)

À̸§:
E-Mail:
Á¦¸ñ:
³»¿ë:
°ü·Ã URL(¼±ÅÃ):
URL Á¦¸ñ(¼±ÅÃ):
°ü·Ã À̹ÌÁö URL:


[ Follow Ups ] [ Post Followup ] [ ÀÚ¹Ù ¹¯°í ´äÇϱâ ]