logo

Java의 오류 반올림

많은 무한한 실수를 유한한 수의 비트로 압축하려면 대략적인 표현이 필요합니다. 대부분의 프로그램은 정수 계산 결과를 최대 32비트 또는 64비트로 저장합니다. 고정된 비트 수가 주어지면 대부분의 실수 계산은 그 많은 비트를 사용하여 정확하게 표현할 수 없는 양을 생성합니다. 따라서 부동 소수점 계산의 결과는 유한 표현에 맞게 다시 반올림되어야 하는 경우가 많습니다. 이 반올림 오류는 부동 소수점 계산의 특징입니다. 따라서 부동 소수점 숫자 계산을 처리하는 동안(특히 계산이 돈을 기준으로 하는 경우) 프로그래밍 언어의 반올림 오류를 처리해야 합니다. 예를 살펴보겠습니다:

Java
public 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 따라서 부동 소수점 변수 안에 저장할 수 없습니다.

또 다른 예:

java
public 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
public 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 특히 큰 분수의 경우 정확성을 제공하도록 설계된 클래스입니다. 다음 프로그램은 오류를 제거하는 방법을 보여줍니다.
Java
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 함수를 사용한 출력 간의 차이를 확인할 수 있습니다.

Java
public 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