CodeGym /Java Blog /무작위의 /Java의 BigDecimal
John Squirrels
레벨 41
San Francisco

Java의 BigDecimal

무작위의 그룹에 게시되었습니다
안녕! 오늘 수업에서는 큰 수에 대해 이야기하겠습니다. 아니요, 정말 크다는 뜻입니다. 우리는 이전에 기본 데이터 유형에 대한 값 범위 테이블을 반복적으로 접했습니다. 다음과 같습니다.
원시 유형 메모리 크기 값 범위
바이트 8비트 -128 ~ 127
짧은 16비트 -32768 ~ 32767
16비트 0 ~ 65536
정수 32비트 -2147483648 ~ 2147483647
64비트 -9223372036854775808 ~ 9223372036854775807
뜨다 32비트 (2의 -149승) ~ ((2의 -23승) * 2의 127승)
더블 64비트 (-2의 63승) ~ ((2의 63승) - 1)
부울 8(배열로 사용하는 경우), 32(배열로 사용하지 않는 경우) 참 또는 거짓
가장 넓은 정수 데이터 유형은 long 입니다 . 부동 소수점 숫자는 double 입니다 . 하지만 필요한 숫자가 너무 커서 long 에도 맞지 않는다면 어떻게 될까요 ? Long 데이터 유형은 가능한 값의 범위가 매우 넓지만 여전히 64비트로 제한됩니다. 초대형 숫자에 100비트가 필요한 경우 어떻게 해야 합니까? 다행히도 우리는 아무것도 발명할 필요가 없습니다. 이와 같은 경우를 위해 Java에는 BigInteger (정수용) 및 BigDecimal 이라는 두 가지 특수 클래스가 있습니다.(부동 소수점 숫자의 경우). 그들을 특별하게 만드는 것은 무엇입니까? 우선 이론적으로 최대 크기가 없습니다. 무한한 메모리를 가진 컴퓨터가 없기 때문에 우리는 "이론적으로"라고 말합니다. 그리고 프로그램이 사용 가능한 메모리 양보다 큰 숫자를 생성하면 물론 프로그램이 작동하지 않습니다. 그러나 그러한 경우는 거의 없습니다. 결과적으로 BigIntegerBigDecimal은 거의 무제한 크기의 숫자를 나타낼 수 있다고 말할 수 있습니다. 이 클래스는 무엇을 위해 사용됩니까? 우선, 매우 엄격한 정확도 요구 사항을 가진 계산을 위해. 예를 들어, 인간의 생명은 일부 프로그램(예: 비행기, 로켓 또는 의료 장비를 제어하는 ​​소프트웨어)의 계산 정확도에 따라 달라질 수 있습니다. 따라서 소수점 이하 150번째 자리가 중요한 경우 BigDecimal최선의 선택입니다. 또한 이 클래스의 개체는 가장 작은 값의 정확한 계산도 매우 중요한 금융 분야에서 자주 사용됩니다. BigIntegerBigDecimal 개체를 어떻게 사용하며 이에 대해 알아야 합니까? 이러한 클래스의 개체는 다음과 같이 생성됩니다.

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigDecimal decimal = new BigDecimal("123.444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444444");
       System.out.println(decimal);
   }
}
문자열을 생성자에 전달하는 것은 가능한 옵션 중 하나일 뿐입니다. 여기서 우리는 숫자가 longdouble 의 최대값을 초과하기 때문에 문자열을 사용합니다. 컴파일러에게 어떤 숫자를 만들고 싶은지 설명할 방법이 필요합니다. 111111111111111111111111111111111111111111111111111111111111111111111 생성자에 대한 작업은 작동하지 않습니다. Java는 전달된 숫자를 기본 데이터 유형 중 하나로 밀어 넣으려고 시도하지만 그 중 어느 것에도 맞지 않습니다. 그렇기 때문에 문자열을 사용하여 원하는 숫자를 전달하는 것이 좋은 선택입니다. 두 클래스 모두 전달된 문자열에서 숫자 값을 자동으로 추출할 수 있습니다. 큰 숫자의 클래스로 작업할 때 기억해야 할 또 다른 중요한 점은 객체가 불변( Immutable )이라는 것입니다. 기본 유형(Integer, Long 등)에 대한 래퍼 클래스 및 String 클래스 에 대한 경험 덕분에 이미 불변성에 대해 잘 알고 있습니다 .

import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       integer.add(BigInteger.valueOf(33333333));
       System.out.println(integer);

   }
}
콘솔 출력:

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 
예상하셨겠지만 저희 번호는 변경되지 않았습니다. 더하기 연산을 수행하려면 연산 결과를 받을 새 객체를 생성해야 합니다.

import java.math.BigInteger;

public class Main {

   public static void main(String[] args) {

       BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
       System.out.println(integer);

       BigInteger result = integer.add(BigInteger.valueOf(33333333));
       System.out.println(result);

   }
}
콘솔 출력:

11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
보세요, 이제 모든 것이 정상적으로 작동합니다 :) 그런데, 덧셈 연산이 얼마나 특이한지 눈치채셨나요?

BigInteger result = integer.add(BigInteger.valueOf(33333333));
이것은 또 다른 중요한 포인트입니다. 큰 숫자 클래스는 + - * / 연산자를 사용하지 않습니다. 대신 일련의 메서드를 제공합니다. 주요 방법에 대해 알아보겠습니다(항상 그렇듯이 Oracle 설명서( 여기여기 )에서 전체 방법 목록을 찾을 수 있습니다 ).
  1. 산술 연산을 위한 메서드: add() , 뺄셈() , multiply() , divide() . 이러한 방법은 각각 덧셈, 뺄셈, 곱셈 및 나눗셈을 수행하는 데 사용됩니다.

  2. doubleValue() , intValue() , floatValue() , longValue() 등은 큰 숫자를 Java의 기본 유형 중 하나로 변환하는 데 사용됩니다. 이러한 방법을 사용할 때는 주의하십시오. 비트 크기의 차이를 잊지 마세요!

    
    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
    
           long result = integer.longValue();
           System.out.println(result);
    
       }
    }
    

    콘솔 출력:

    
    8198552921648689607
    
  3. min()max()를 사용 하면 두 개의 큰 숫자의 최소값과 최대값을 찾을 수 있습니다.
    이러한 메서드는 정적이 아닙니다!

    
    import java.math.BigInteger;
    
    public class Main {
    
       public static void main(String[] args) {
    
           BigInteger integer = new BigInteger("11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
           BigInteger integer2 = new BigInteger("222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");
    
           System.out.println(integer.max(integer2));
    
       }
    }
    

    콘솔 출력:

    
    222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
    

BigDecimal 반올림 동작

큰 숫자를 반올림하고 반올림 동작을 구성하는 것이 그렇게 간단하지 않기 때문에 이 항목에는 별도의 섹션이 있습니다. setScale() 메소드를 사용하여 BigDecimal 의 소수 자릿수를 설정할 수 있습니다 . 예를 들어 숫자 111.5555555555의 소수점 이하 세 자리를 원한다고 가정합니다. 그러나 숫자 3을 setScale() 메서드 에 인수로 전달하여 원하는 결과를 얻을 수 없습니다 . 위에서 언급했듯이 BigDecimal계산 정밀도에 대한 엄격한 요구 사항이 있는 숫자를 표현하기 위한 것입니다. 현재 형식에서 숫자는 소수점 이하 10자리입니다. 7개를 버리고 3개만 남기고자 합니다. 따라서 숫자 3 외에 반올림 모드를 통과해야 합니다. BigDecimal에는 총 8개의 반올림 모드가 있습니다. 많이! 그러나 계산의 정밀도를 미세하게 조정해야 한다면 필요한 모든 것을 갖추게 될 것입니다. BigDecimal 에서 제공하는 8가지 반올림 모드는 다음과 같습니다 .
  1. ROUND_CEILING — 반올림

    
    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
    
  2. ROUND_DOWN — 0으로 반올림

    
    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
    
  3. ROUND_FLOOR — 내림

    
     111.5555555555 -> setScale(3, ROUND_FLOOR) -> 111.555
    
    

  4. ROUND_HALF_UP — 소수점 이하 숫자 >= 0.5인 경우 반올림

    
    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
    
  5. ROUND_HALF_DOWN — 소수점 이하 숫자 > 0.5인 경우 반올림

    
    0.55 -> setScale(1, ROUND_HALF_DOWN) -> 0.5
    0.56 -> setScale(1, ROUND_HALF_DOWN) -> 0.6
    
  6. ROUND_HALF_EVEN — 반올림은 소수점 왼쪽에 있는 숫자에 따라 달라집니다. 왼쪽의 숫자가 짝수이면 반올림됩니다. 소수점 왼쪽의 숫자가 홀수이면 반올림됩니다.

    
    2.5 -> setScale(0, ROUND_HALF_EVEN) -> 2
    

    소수점 왼쪽의 숫자는 2(짝수)입니다. 숫자는 내림합니다. 소수점 이하 자릿수 0을 원하므로 결과는 2입니다.

    
    3.5 -> setScale(0, ROUND_HALF_EVEN) -> 4
    

    소수점 왼쪽의 숫자는 3(홀수)입니다. 숫자는 반올림됩니다. 우리는 소수 자릿수가 0이기를 원하므로 결과는 4입니다.

  7. ROUND_UNNECCESSARY — 이 모드는 반올림 모드를 메서드에 전달해야 하지만 숫자를 반올림할 필요가 없는 경우에 사용됩니다. ROUND_UNNECCESSARY 모드가 설정된 상태에서 숫자를 반올림하려고 하면 ArithmeticException이 발생합니다.

    
    3.51 -> setScale(1, ROUND_UNNECCESSARY) -> ArithmeticException
    
  8. ROUND_UP — 0에서 멀어지는 방향으로 반올림합니다.

    
    111.5551 -> setScale(3, ROUND_UP) -> 111.556
    

큰 숫자 비교

이것은 또한 중요합니다. equals() 메서드를 사용하여 Java에서 개체를 비교한다는 것을 기억할 것입니다 . 구현은 언어 자체(표준 Java 클래스의 경우)에서 제공하거나 프로그래머가 재정의합니다. 그러나 BigDecimal 객체 의 경우 비교를 위해 equals() 메서드를 사용하는 것은 권장되지 않습니다. BigDecimal.equals() 메서드는 2개의 숫자가 동일한 값과 배율을 갖는 경우에만 true를 반환하기 때문입니다 . DoubleBigDecimal 클래스 에 대한 equals() 메서드 의 동작을 비교해 보겠습니다 .

import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       Double a = 1.5;
       Double b = 1.50;

       System.out.println(a.equals(b));

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.equals(y));
      
   }
}
콘솔 출력:

true 
false
보시 다시피 BigDecimal 의 경우 숫자 1.5와 1.50이 같지 않은 것으로 나타났습니다! 이것은 정확히 BigDecimal 클래스 의 equals() 메소드 구현의 특성 때문이었습니다 . 두 개의 BigDecimal 객체를 보다 정확하게 비교하려면 compareTo() 메서드를 사용하는 것이 좋습니다 .

import java.math.BigDecimal;

public class Main {

   public static void main(String[] args) {

       BigDecimal x = new BigDecimal("1.5");
       BigDecimal y = new BigDecimal("1.50");

       System.out.println(x.compareTo(y));

   }
}
콘솔 출력:

0
compareTo () 메서드는 0을 반환했으며 이는 1.5와 1.50이 같다는 것을 의미합니다. 그리고 이것은 우리가 예상한 결과입니다! :) 이것으로 오늘 수업을 마칩니다. 이제 작업으로 돌아갈 시간입니다! :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION