double 형 사칙연산 오차에 대해 테스트 하던중... 두 값의 오차값을 계산하기 위해 확인을 해봤더니... 지수로 표기된다.
항상 지수가 나오면 인터넷 검색에 의존하다 이렇게 직접 정리를 하면 머리에 오래 남을 것같아.. 이렇게 끄적끄적... ^^;
# 지수란?
지수 (Exponenital)는 E 로 표기한다. 과학이나 공학에서 아주 큰 숫자를 간단히 표기하기 위해 사용한다고 한다.
10^2 에서 2를 지수라고 한다.
# 지수 표기법은 계수 뒤에 E 를 붙이고 위에 지수값을 넣으면 된다. 지수 표기법에서 E = 10 을 뜻한다.
ex)
0.000000000002 를 지수로 표기하면 2E-12 ( 2 * 10^-12 )가 된다.
Java의 Double 형 사칙연산 오차
어제 술자리에서 다른 개발자가 Double 형 사칙연산시 오차범위가 발생하는 내용에 대해 얘기했다..
헉.. 금시초문이다... ㅡㅡ;; 난 왜 처음 알았지...? ^^;;
아침에 출근하자 마자 눈으로 확인... 정말.... 그렇다....
System.out.println(11000 * 1.15);
==> 12649.999999999998 (12650.00 값이 나올줄 알았는데...)
그래서 검색을 해보니.... float과 double 형은 빠르게 근사치로 계산 하기위해 만들어졌다고 한다..
그럼 double 형을 계산 할때는 어떻게 해야하나... BigDecimal을 이용하는 방법이 있다고 한다.
헌데... 아래와 같이 테스트를 해보니....헉... 그래도 오차범위가 생긴다....
System.out.println(new BigDecimal(11000).multiply(new BigDecimal(1.15)));
==> 12649.999999999999023003738329862244427204132080078125000
위와 같은 결과가 나오는건.. BigDecimal을 생성할때 double 형을 매개변수로 전달해서 그렇다.
이때 double형이 전달되면 그자체로 double 형이 오차를 포함하고 있어서 그렇다고 한다.
이문제를 해결하려면 BigDecimal을 생성할때 매개변수로 String 값을 전달하는 거다.
System.out.println(new BigDecimal("11000").multiply(new BigDecimal("1.15")));
==> 12650.00 (이제 정상적인 값이 나왔다.)
log4j.xml 설정
<appender name="아무이름1" class="org.apache.log4j.DailyRollingFileAppender">
<param name="file" value="로그 쌓을 패스/파일명.log"/>
<param name="Append" value="true"/>
<param name="DatePattern" value="'.'날짜형식(yyyymmdd)"/><!-- 파일명에 붙일 날짜형식 -->
<layout class="org.apache.log4j.PatternLayout"><!-- 레이아웃 설정 -->
<param name="ConversionPattern" value="%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n"/>
<!--로그에 남길내용 #아래참조-->
</layout>
</appender>
<logger name="패키지명(com.tinocomm.widget.web)" additivity="false">
<!-- additivity="false" 를 주면 로그가 중복으로 찍히는걸 막음 -->
<level value="로그 레벨설정"/>
<appender-ref ref="아무이름1" />
</logger>
#ConversionPattern
%p debug, info, warn, error, fatal 등의 priority 가 출력된다.
%m 로그내용이 출력됩니다
%d 로깅 이벤트가 발생한 시간을 기록합니다.
포맷은 %d{HH:mm:ss, SSS}, %d{yyyy MMM dd HH:mm:ss, SSS}같은 형태로 사용하며 SimpleDateFormat에 따른 포맷팅을 하면 된다
%t 로그이벤트가 발생된 쓰레드의 이름을 출력합니다.
%% % 표시를 출력하기 위해 사용한다.
%n 플랫폼 종속적인 개행문자가 출력된다. rn 또는 n 일것이다.
%c 카테고리를 표시합니다
예) 카테고리가 a.b.c 처럼 되어있다면 %c{2}는 b.c가 출력됩니다.
%C 클래스명을 포시합니다.
예)클래스구조가 org.apache.xyz.SomeClass 처럼 되어있다면 %C{2}는 xyz.SomeClass 가 출력됩니다
%F 로깅이 발생한 프로그램 파일명을 나타냅니다.
%l 로깅이 발생한 caller의 정보를 나타냅니다
%L 로깅이 발생한 caller의 라인수를 나타냅니다
%M 로깅이 발생한 method 이름을 나타냅니다.
%r 어플리케이션 시작 이후 부터 로깅이 발생한 시점의 시간(milliseconds)
%x 로깅이 발생한 thread와 관련된 NDC(nested diagnostic context)를 출력합니다.
%X 로깅이 발생한 thread와 관련된 MDC(mapped diagnostic context)를 출력합니다.