JavaRush /Java Blog /Random-KO /Java의 BigDecimal

Java의 BigDecimal

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 강의에서는 큰 숫자에 대해 이야기하겠습니다. 아니요, 정말 큰 것들에 대해서요. 이전에 우리는 기본 데이터 유형의 값 범위 테이블을 두 번 이상 보았습니다. 다음과 같습니다.
기본 유형 메모리 크기 값의 범위
바이트 8비트 -128~127
짧은 16비트 -32768부터 32767까지
16비트 0부터 65536까지
정수 32비트 -2147483648에서 2147483647까지
64비트 -9223372036854775808에서 9223372036854775807까지
뜨다 32비트 (2의 -149승)에서 ((2-2의 -23)*2의 127승)까지
더블 64비트 (-2의 63승)에서 ((2의 63승) - 1)까지
부울 8(배열에 사용되는 경우), 32(비배열에 사용되는 경우) 참 또는 거짓
정수에 관해 이야기할 때 가장 용량이 큰 데이터 유형은 long 이고, 부동 소수점 숫자에 대해 이야기할 때는 double 입니다 . 하지만 필요한 숫자가 너무 커서 long 에도 맞지 않으면 어떻게 될까요 ? 가능한 Long 값의 범위는 상당히 크지만 여전히 특정 크기(64비트)로 제한됩니다. 매우 큰 숫자의 무게가 100비트라면 어떻게 될까요? 다행히도 아무것도 발명할 필요가 없습니다. Java에서는 이러한 경우를 위해 BigInteger (정수용) 및 BigDecimal (부동 소수점 숫자용)이라는 두 개의 특수 클래스가 생성되었습니다. 그들의 특징은 무엇입니까? 우선, 이론적으로 최대 크기가 없습니다. 이론적으로 무한한 메모리를 갖춘 컴퓨터는 없기 때문입니다. 그리고 프로그램에서 컴퓨터 메모리 크기보다 큰 숫자를 생성하면 당연히 프로그램이 작동하지 않습니다. 그러나 그러한 경우는 거의 없습니다. 따라서 숫자의 크기는 사실상 무제한이라고 말할 수 BigInteger있습니다 BigDecimal. 이 수업은 무엇을 위해 사용됩니까? 우선, 매우 높은 정확도가 요구되는 계산에 사용됩니다. 예를 들어 인간의 생명이 계산의 정확성에 달려 있는 프로그램(비행기, 로켓 또는 의료 장비용 소프트웨어)이 있습니다. 따라서 소수점 이하 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);
   }
}
문자열을 매개변수로 전달하는 것은 가능한 생성자 중 하나일 뿐입니다. 여기서는 숫자가 최대값 long및 를 초과하기 때문에 문자열을 사용합니다 double. 어떻게든 우리가 얻고자 하는 숫자가 무엇인지 정확히 컴파일러에 설명해야 합니다. 1111111111111111111111111111111111111111111111111111 111111111111111111111111111111111111111111111111111111111111111 작동하지 않습니다. : Java는 "적합"을 시도합니다. 전달된 숫자를 기본 데이터 유형 중 하나로 변환하지만 그 중 어느 것에도 맞지 않습니다. 따라서 문자열을 사용하여 원하는 숫자를 전달하는 것이 좋은 옵션입니다. 두 클래스 모두 전달된 문자열에서 숫자 값을 자동으로 추출할 수 있습니다. 많은 수의 클래스로 작업할 때 기억해야 할 또 다른 중요한 점은 해당 객체가 변경 불가능하다는 것입니다( Immutable) . String당신은 프리미티브(Integer, Long 등)에 대한 클래스와 래퍼 클래스의 예를 통해 이미 불변성의 원칙에 대해 잘 알고 있습니다 .
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);

   }
}
콘솔 출력:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
예상하셨듯이 우리 숫자는 변하지 않았습니다. 덧셈 작업이 성공하려면 새 개체를 만들고 여기에 덧셈 결과를 할당해야 합니다.
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);

   }
}
콘솔 출력:

1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111144444444
이제 모든 것이 정상적으로 작동합니다. :) 그런데 추가 작업이 얼마나 특이한지 보셨나요?
BigInteger result = integer.add(BigInteger.valueOf(33333333));
이것은 또 다른 중요한 포인트입니다. 큰 수의 클래스는 연산에 +-*/ 연산자를 사용하지 않고 대신 메서드 세트를 제공합니다. 주요 메소드를 살펴보겠습니다(언제나 그렇듯이 Oracle 문서( 여기여기 )에서 전체 메소드 목록을 찾을 수 있습니다 ).
  1. 산술 연산을 수행하는 방법: add() , subtract(), 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 반올림 제어

이 주제는 큰 숫자를 반올림하고 조정하는 것이 그렇게 간단한 일이 아니기 때문에 별도의 섹션에 포함되어 있습니다. BigDecimal를 사용하여 숫자의 소수 자릿수를 설정할 수 있습니다 setScale(). 예를 들어 숫자 111.5555555555 의 정밀도를 소수점 이하 세 자리로 설정하려고 합니다. setScale()그러나 숫자 3을 메서드에 대한 인수로 전달하여 문제를 해결할 수는 없습니다 . 위에서 언급했듯이 BigDecimal이는 정확도가 향상된 계산을 위한 숫자입니다. 현재 형식에서는 숫자의 소수점 이하 10자리가 표시됩니다. 그 중 7개를 버리고 3개만 남기고 싶습니다. 따라서 숫자 3 외에 반올림 모드를 매개변수로 전달해야 합니다 . 총 8개의 반올림 모드가 있습니다 BigDecimal. 꽤 많이! 그러나 프로그램에서 계산의 정확성을 실제로 미세 조정해야 한다면 이에 필요한 모든 것이 갖추어져 있을 것입니다. 다음은 사용 가능한 8가지 반올림 모드입니다 BigDecimal.
  1. ROUND_CEILING- 반올림

    111.5555555555 -> setScale(3, ROUND_CEILING) -> 111.556
  2. ROUND_DOWN- 방전 폐기

    111.5555555555 -> setScale(3, ROUND_DOWN) -> 111.555
  3. ROUND_FLOOR- 반올림

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

  4. ROUND_HALF_UP— 소수점 이하의 숫자가 .5보다 크면 반올림합니다.

    0.55 -> setScale(1, ROUND_HALF_UP) -> 0.6
    0.54 -> setScale(1, ROUND_HALF_UP) -> 0.5
  5. ROUND_HALF_DOWN— 소수점 이하의 숫자가 .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- 반올림.

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

큰 숫자의 비교

이 질문도 중요합니다. 이 메소드가 Java에서 객체를 비교하는 데 사용된다는 것을 이미 기억하고 있습니다 equals(). 이는 언어 자체(Java 내장 클래스의 경우)에 의해 제공되거나 프로그래머에 의해 재정의됩니다. 그러나 클래스 객체의 경우에는 비교 BigDecimal방법을 사용 하지 않는 것이 좋습니다. equals()그 이유는 BigDecimal.equals()두 숫자 메서드가 두 숫자의 값과 크기가 동일한 경우에만 true를 반환하기 때문입니다. y 와 y 메서드 의 동작을 비교해 보겠습니다 . equals()DoubleBigDecimal
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
보시다시피 c의 경우 숫자 1.5와 1.50은 BigDecimal동일하지 않은 것으로 나타났습니다! equals()이는 클래스에 있는 메소드의 특성 때문에 정확하게 발생했습니다 BigDecimal. 둘을 보다 정확하게 비교하려면 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