많은 무한한 실수를 유한한 수의 비트로 압축하려면 대략적인 표현이 필요합니다. 대부분의 프로그램은 정수 계산 결과를 최대 32비트 또는 64비트로 저장합니다. 고정된 비트 수가 주어지면 대부분의 실수 계산은 그 많은 비트를 사용하여 정확하게 표현할 수 없는 양을 생성합니다. 따라서 부동 소수점 계산의 결과는 유한 표현에 맞게 다시 반올림되어야 하는 경우가 많습니다. 이 반올림 오류는 부동 소수점 계산의 특징입니다. 따라서 부동 소수점 숫자 계산을 처리하는 동안(특히 계산이 돈을 기준으로 하는 경우) 프로그래밍 언어의 반올림 오류를 처리해야 합니다. 예를 살펴보겠습니다:
Javapublic class Main { public static void main(String[] args) { double a = 0.7; double b = 0.9; double x = a + 0.1; double y = b - 0.1; System.out.println('x = ' + x); System.out.println('y = ' + y ); System.out.println(x == y); } }
자바의 스캐너
산출:
x = 0.7999999999999999
y = 0.8
false
여기서 대답은 Java 컴파일러가 수행한 반올림 이유가 예상했던 것과 다릅니다.
반올림 오류의 원인
Float 및 Double 데이터 유형은 IEEE 부동 소수점 754 사양을 구현합니다. 즉, 숫자는 다음과 같은 형식으로 표현됩니다.
SIGN FRACTION * 2 ^ EXP 0.15625 = (0.00101)2부동 소수점 형식에서는 1.01 * 2^-3으로 표시됩니다.
모든 분수가 2의 거듭제곱의 분수로 정확하게 표현될 수 있는 것은 아닙니다. 간단한 예로 0.1 = (0.000110011001100110011001100110011001100110011001100110011001…)2 따라서 부동 소수점 변수 안에 저장할 수 없습니다.
또 다른 예:
javapublic class Main { public static void main(String[] args) { double a = 0.7; double b = 0.9; double x = a + 0.1; double y = b - 0.1; System.out.println('x = ' + x); System.out.println('y = ' + y ); System.out.println(x == y); } }
산출:
x = 0.7999999999999999
y = 0.8
false
또 다른 예:
Javapublic class Main { public static void main(String args[]) { double a = 1.0; double b = 0.10; double x = 9 * b; a = a - (x); // Value of a is expected as 0.1 System.out.println('a = ' + a); } }
산출:
a = 0.09999999999999998반올림 오류를 수정하는 방법은 무엇입니까?
- 결과를 반올림합니다. Round() 함수를 사용하면 부동 소수점 산술 저장 부정확성으로 인한 영향을 최소화할 수 있습니다. 사용자는 계산에 필요한 소수 자릿수로 숫자를 반올림할 수 있습니다. 예를 들어 통화 작업을 하는 동안 소수점 이하 2자리로 반올림할 수 있습니다.
- 알고리즘 및 기능: 이러한 경우를 처리하려면 수치적으로 안정적인 알고리즘을 사용하거나 고유한 기능을 설계하세요. 정확하지 않은 숫자를 자르거나 반올림할 수 있습니다. (연산의 수치 정밀도도 계산할 수 있습니다.)
- BigDecimal 클래스: 당신은 사용할 수 있습니다 java.math.BigDecimal 특히 큰 분수의 경우 정확성을 제공하도록 설계된 클래스입니다. 다음 프로그램은 오류를 제거하는 방법을 보여줍니다.
import java.math.BigDecimal; import java.math.RoundingMode; public class Main { public static void main(String args[]) { BigDecimal a = new BigDecimal('1.0'); BigDecimal b = new BigDecimal('0.10'); BigDecimal x = b.multiply(new BigDecimal('9')); a = a.subtract(x); // Rounding to 1 decimal place a = a.setScale(1 RoundingMode.HALF_UP); System.out.println('a = ' + a); } }
산출:
0.1여기 a = a.setScale(1 RoundingMode.HALF_UP);
라운드 aHALF_UP 반올림 모드를 사용하여 소수점 이하 1자리까지. 따라서 BigDecimal을 사용하면 재무 계산이나 정밀도가 중요한 기타 경우에 특히 유용할 수 있는 산술 및 반올림 작업을 보다 정확하게 제어할 수 있습니다.
중요 사항:
Math.round는 값을 가장 가까운 정수로 반올림합니다. 0.10은 1보다 0에 더 가까우므로 0으로 반올림됩니다. 반올림하고 1.0으로 나눈 결과는 0.0입니다. 따라서 BigDecimal 클래스와 Maths.round 함수를 사용한 출력 간의 차이를 확인할 수 있습니다.
Javapublic class Main { public static void main(String args[]) { double a = 1.0; double b = 0.10; double x = 9 * b; a = a - (x); /* We use Math.round() function to round the answer to closest long then we multiply and divide by 1.0 to to set the decimal places to 1 place (this can be done according to the requirements.*/ System.out.println('a = ' + Math.round(a*1.0)/1.0); } }
산출:
0.0