Sunday, October 08, 2006
자바/Java] 부동소수점 연산 오차 수정 출력하기 - Floating-Point: 9.7-9.0, 0.6-0.4
2001년도에 떠들썩했던 문제가 있었습니다.
엑셀과 윈도우 계산기에서
9.7 - 9.0 = 0.7 (0.6999999999999993)
0.6 - 0.4 = 0.2 (0.19999999999999996)
위의 계산 결과가 정확하지 않고 0.6999999999999993 / 0.19999999999999996 등으로 나온다는 것이었습니다.
지금은 정확한 값이 나오더군요. MS에서 손을 좀 본 것 같기도 합니다. 물론 MS의 잘못이 아니라 IEEE 754 표준의 한계인 것으로 알고 있습니다.
그런데 자바에는 그런 오차가 계속 나오고 있었습니다.
다만, 아래의 소스처럼 System.out.format()으로 값을 다듬어서 출력하니 정확한 값이 나왔습니다. format() 은 내부적으로 실수를 반올림하기 때문에 그런 것 같습니다.
"%.1f" 이렇게 하면 소수점 1자리까지만 출력되어 결과가 더 깔끔해집니다.
출력 결과:
엑셀과 윈도우 계산기에서
9.7 - 9.0 = 0.7 (0.6999999999999993)
0.6 - 0.4 = 0.2 (0.19999999999999996)
위의 계산 결과가 정확하지 않고 0.6999999999999993 / 0.19999999999999996 등으로 나온다는 것이었습니다.
지금은 정확한 값이 나오더군요. MS에서 손을 좀 본 것 같기도 합니다. 물론 MS의 잘못이 아니라 IEEE 754 표준의 한계인 것으로 알고 있습니다.
그런데 자바에는 그런 오차가 계속 나오고 있었습니다.
다만, 아래의 소스처럼 System.out.format()으로 값을 다듬어서 출력하니 정확한 값이 나왔습니다. format() 은 내부적으로 실수를 반올림하기 때문에 그런 것 같습니다.
public class Foo {
public static void main(String[] args) {
System.out.println(0.3 - 0.4);
System.out.println(0.4 - 0.4);
System.out.println(0.5 - 0.4);
System.out.println(0.6 - 0.4);
System.out.println(0.7 - 0.4);
System.out.println(0.8 - 0.4);
System.out.println(0.9 - 0.4);
System.out.println(1.0 - 0.4);
System.out.println(9.7 - 9.0);
System.out.println("--------------------------------");
System.out.format("%f%n", 0.3 - 0.4);
System.out.format("%f%n", 0.4 - 0.4);
System.out.format("%f%n", 0.5 - 0.4);
System.out.format("%f%n", 0.6 - 0.4);
System.out.format("%f%n", 0.7 - 0.4);
System.out.format("%f%n", 0.8 - 0.4);
System.out.format("%f%n", 0.9 - 0.4);
System.out.format("%f%n", 1.0 - 0.4);
System.out.format("%f%n", 9.7 - 9.0);
System.out.println("--------------------------------");
System.out.format("%.1f%n", 0.3 - 0.4);
System.out.format("%.1f%n", 0.4 - 0.4);
System.out.format("%.1f%n", 0.5 - 0.4);
System.out.format("%.1f%n", 0.6 - 0.4);
System.out.format("%.1f%n", 0.7 - 0.4);
System.out.format("%.1f%n", 0.8 - 0.4);
System.out.format("%.1f%n", 0.9 - 0.4);
System.out.format("%.1f%n", 1.0 - 0.4);
System.out.format("%.1f%n", 9.7 - 9.0);
}
}
public static void main(String[] args) {
System.out.println(0.3 - 0.4);
System.out.println(0.4 - 0.4);
System.out.println(0.5 - 0.4);
System.out.println(0.6 - 0.4);
System.out.println(0.7 - 0.4);
System.out.println(0.8 - 0.4);
System.out.println(0.9 - 0.4);
System.out.println(1.0 - 0.4);
System.out.println(9.7 - 9.0);
System.out.println("--------------------------------");
System.out.format("%f%n", 0.3 - 0.4);
System.out.format("%f%n", 0.4 - 0.4);
System.out.format("%f%n", 0.5 - 0.4);
System.out.format("%f%n", 0.6 - 0.4);
System.out.format("%f%n", 0.7 - 0.4);
System.out.format("%f%n", 0.8 - 0.4);
System.out.format("%f%n", 0.9 - 0.4);
System.out.format("%f%n", 1.0 - 0.4);
System.out.format("%f%n", 9.7 - 9.0);
System.out.println("--------------------------------");
System.out.format("%.1f%n", 0.3 - 0.4);
System.out.format("%.1f%n", 0.4 - 0.4);
System.out.format("%.1f%n", 0.5 - 0.4);
System.out.format("%.1f%n", 0.6 - 0.4);
System.out.format("%.1f%n", 0.7 - 0.4);
System.out.format("%.1f%n", 0.8 - 0.4);
System.out.format("%.1f%n", 0.9 - 0.4);
System.out.format("%.1f%n", 1.0 - 0.4);
System.out.format("%.1f%n", 9.7 - 9.0);
}
}
"%.1f" 이렇게 하면 소수점 1자리까지만 출력되어 결과가 더 깔끔해집니다.
출력 결과:
-0.10000000000000003
0.0
0.09999999999999998
0.19999999999999996
0.29999999999999993
0.4
0.5
0.6
0.6999999999999993
--------------------------------
-0.100000
0.000000
0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
--------------------------------
-0.1
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.0
0.09999999999999998
0.19999999999999996
0.29999999999999993
0.4
0.5
0.6
0.6999999999999993
--------------------------------
-0.100000
0.000000
0.100000
0.200000
0.300000
0.400000
0.500000
0.600000
0.700000
--------------------------------
-0.1
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
tag: java
자바 | Java
<< Home