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 클래스를 사용한다.

먼저 1번 방법을 사용해보려고 Math 클래스의 메소드들을 들여다 봤습니다. return type이 전부 정수 형태 입니다.
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#]

두 번째 방법인 BIgDecimal을 사용해보겠습니다.
[#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#]

번외로 Wrapper 클래스를 가지고도 해봤습니다.
[#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를 보겠습니다.