Java에서 실수 표현 부정확성
Agile Java 4장 번역서 p180~p181에 걸쳐 실수 표현의 부정확함에 대한 내용이 나옵니다. 어떤 문제가 있으면 어떻게 해결할 수 있을지 고민해 봅니다.
먼저 float로 테스트를 해봤습니다.
[#M_ more.. | less.. |
import static org.junit.Assert.*;
import org.junit.Test;
public class FloatTest {
@Test
public void floatMultyply(){
float value = 0.3f * 3;
assertEquals(0.9, value);
}
}
이 테스트 코드의 결과는 fail입니다.
1139388268.bmp
_M#]
double로도 테스트를 해봤습니다.
[#M_ more.. | less.. |
@Test
public void doubleMultifly(){
double value = 0.3 * 3;
assertEquals(0.9, value);
}
결과
1140320167.bmp
_M#]
해결책으로 제시된 방법은
1. 반올림을 사용한다.
2. BIgDecimal 클래스를 사용한다.
1185064946.bmp
이걸 사용해서 실수를 반올림하면 조금 난감한 상황이 발생할 것 같습니다. -_-;;;
DecimalFormat class를 사용해봤습니다.
[#M_ more.. | less.. |
public class FloatTest {
@Test
public void floatMultyply(){
float value = 0.3f * 3;
DecimalFormat df = new DecimalFormat("#.0");
assertEquals(0.9, df.format(value));
}
@Test
public void doubleMultifly(){
double value = 0.3 * 3;
DecimalFormat df = new DecimalFormat("#.0");
assertEquals(0.9, df.format(value));
}
}
결과는
1205979505.bmp이런 어처구니 없는 결과가 있나. # 때문인것 같아서 #을 0으로 바꿔보았습니다. 그랬더니 결과는
1032824768.bmp더 어처구니 없는 결과가 나왔습니다. -_-;;;; 아 난감해...
_M#]
[#M_ more.. | less.. |
@Test
public void bigDecimalFormat(){
BigDecimal value = new BigDecimal(0.3);
BigDecimal three = new BigDecimal(3);
value = value.multiply(three);
assertEquals(0.9, value);
}
결과는
1323618597.bmpBigDecimalFormat을 사용하더라도 길이만 길어졌을 뿐 정확하진 않습니다. 여기서도 역시 반올림을 사용해줘야 할 것 같습니다. API를 뒤져서 MathContext라는 녀석을 찾았습니다.
소스코드를 다음과 같이 변경합니다.
@Test
public void bigDecimalFormat(){
BigDecimal value = new BigDecimal(0.3);
BigDecimal three = new BigDecimal(3);
MathContext mc = new MathContext(1);
value = value.multiply(three, mc);
assertEquals(0.9, value);
}
결과는
1246165719.bmp헉.. 역시 또 어처구니 없는 결과가... assert에 무슨 문제라도 있는 것일까요?
_M#]
[#M_ more.. | less.. |
@Test
public void floatObjectMultuply(){
Float value = new Float(0.3);
value = value * 3;
assertEquals(0.9, value);
}
결과는
1075121918.bmp
_M#]
참고할 곳 : http://www.javaservice.net/~java/bbs/read.cgi?m=devtip&b=javatip&c=r_p&n=1118831957&p=3&s=t
http://javaservice.net/~java/bbs/read.cgi?m=resource&b=qna2&c=r_p&n=1118716242&p=1&s=t#1118716242
http://docs.sun.com/source/806-3568/ncg_goldberg.html <--- 완전 수학 문서;;
위에서 발생했던 이상한 현상(0.9, 0.9 같은데도 다르다고 하던 현상)이 민재님 덕분에 해결됐습니다. assertion을 할 때 같은 type끼리 비교를 해야되는데.. 하나는 double이고 하나는 BigDecimal이였기 때문에 같은 0.9여도 fail로 나온 것입니다.
assertion을 할 때 두개의 인자만 줄 수 있는 것이 아니라 세번째 인자도 줄 수가 있는데요. API를 보겠습니다.