검색결과 리스트
글
[기초] 부동소수점의 한계, 2진 소수점 표현의 한계
Q. 부동소수점의 표현의 한계에 대해 알아보자.
1. double 형 0.333
1 2 | double dbl = 0.333;System.out.println( dbl ); |
위 소스의 값은 0.333이 나온다. 그러므로 다른 사람들은 이것에 이의를 제기 하지 않았을 것이다.
하지만, 2진 변환 과정에서 위 수치 계산은 무한히 반복된다.
IEEE754 배정도 실수 유효 비트수인 52비트까지를 표현하면 아래와 같다,
0011111111010101010011111101111100111011011001000101101000011101 (2진수)
이 계산은 무한히 반복됨에도 불구하고 double 형이
표현할수 있는 비트 수의 제한이 있으므로 정확한 값의 표현이 불가능하다.
위의 숫자를 소수 60자리로 하여 10진수로 표현하면 아래와 같다.
0.333000000000000018207657603852567262947559356689453125000000 (10진수)
실제로 입력은 0.333이지만
시스템 내부에서 갖고 있는 근사치는 0.3330000000000000182.... 과 같다.
하지만 System.out.println( dbl ); 의 값은 0.333 이 나온다?
그것은 System.out.println( double ); 을 따라가 보면
sun.misc.FloatingDecimal.getChars 이 메소드가 포메팅을 수행하여
보기좋은 숫자 (내부적으로는 0.333의 가장 근사치인) 0.333 이라는 결과를 나타낸다.
2. double형 4.35 * 0.9 = 값은?
윈도우 계산기로 두드려본 결과 3.915 가 나온다.
프로그램도 같을까 ?
1 2 3 4 | double a = 0.9;double b = 4.35;System.out.println( a * b ); |
위의 결과값은 3.9149999999999996 이다.
궁금하면 이클립스 실행 ㄱㄱ
이는 3.915의 가장 가까운 근사치이다.
우리 회사에서 제공하는 Round 함수는 (java JDK 6.x 기반)
Round(수식, 반올림자릿수)
Round(1/3, 3) 의 연산이 0.333 이 나와야 하는 경우가 있다.
하지만 double 형을 채택하고 있는 위 함수는 0.333을 표현할 수 없다.
그래서 !
Round_Fuzz 라는 임의값을 더하여 보정을 하고 있다.
Round_Fuzz 의 임의값을 정해야 하는데,
Round_Fuzz 값이 너무 낮으면,
3.9149999999999996
0.0000000000000001 을 더하게 되면 (Round_Fuzz)
3.9149999999999997 이 되서 아무런 변화가 없게 되고
Round_Fuzz 값이 너무 높으면, 당연히 오차 범위가 커지게 된다.
그래서 아래와 같은 소스를 돌려본 결과
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | double n = 10000.285;Random rand = new Random( System.currentTimeMillis() );for( int i = 0; i < 1000; i++ ){ double op1 = rand.nextDouble() * (double)( i % 10 + 1 ); double op2 = 1.0 / op1; if( i % 2 == 0 ) n = n * op1 * op2; else n = Math.pow( Math.pow( n, op1 ), op2 ); System.out.println( new BigDecimal( n ) ); Math.round( n );} |
통계적으로 그나마 0.00000000001 이 적합하다고 계산된다.
3. 결론
컴퓨터라고 해서 초 정밀한 결과를 내주는것은 아니며,
double 형의 제길슨한 2진 표현 방식은 너무도 어렵기 때문에,
한참을 들여다 보지 않는 이상 "나는" 알수가 없었고,
double 은 double 의 곱의 결과가 어쩌면 약간의 오차가 나올수 있다.
컴터는 어렵다 (ㅠ_ㅠ)
'program > program_basic' 카테고리의 다른 글
| [특수문자] 키보드 특수문자 기호, 키보드 특수문자 이름, Special characters (0) | 2012.10.09 |
|---|
