Dico

[Java] package java.util 02

package java.util

java.math.Biglnteger

내부적으로 int 배열을 사용해서 long 타입보다 훨씬 큰 값을 다룬다.

long 타입보다 성능이 떨어진다.

불변(Immutable).

부호를 따로 저장하고 배열에는 값 자체만 저장한다.

final int signum;       // 부호.
final int[] mag;        // 값 magnitude

signum의 값이 음수인 경우, 2의 보수법에 맞게 mag의 값을 변환해서 처리한다.

생성

문자열로 숫자를 표현하는 것이 일반적.

정수형 리터럴로는 표현할 수 있는 값의 한계가 있다.

BigInteger bi;
bi = new BigInteger("12345678901234567890");
bi = new BigInteger("LOVE", 16);
bi = BigInteger.valueOf(1234567890L);

다른 타입으로의 변환

  • 문자열 또는 지정된 진법(radix)의 문자열로 변환
String toString()
String toString(int radix)
  • byte 배열로 변환
byte[] toByteArray()
  • Number부터 상속받은 기본형으로 변환
int intvalue()
long longValue()
float floatValue()
double doubleValue()
  • 정수형으로 변환하는 메서드 중 이름 끝에 Exact가 붙은 메서드

     변환한 결과가 변환한 타입의 범위에 속하지 않으면 ArithmeticExceptin을 발생시킨다.

byte byteValueExact()
int intValueExact()
long longValueExact()

연산

정수형에 사용할 수 있는 모든 연산자와 수학적인 계산을 쉽게 해주는 메서드들이 정의되어 있다.

BigInteger add(BigInteger val)         // this + val
BigInteger subtract(BigInteger val)    // this - val
BigInteger multiply(BigInteger val)    // this * val
BigInteger divide(BigInteger val)      // this / val
BigInteger remainder(BigInteger val)   // this % val

BigInteger는 불변이므로, 새로운 인스턴스가 반환된다.

비트 연산 메서드

큰 숫자를 다루기 때문에 성능을 향상시키기 위해 비트단위로 연산을 수행하는 메서드들이 많다.

반환타입이름설명
   int   bitCount()   2진수로 표현했을 때, 1의 개수(음수는 0의 개수)를 반환
   int   bitLength()   2진수로 표현했을 때, 값을 표현하는 데 필요한 bit수
   boolean   testBit(int n)   우측에서 n+1번째 비트가 1이면 true, 0이면 false
   BigInteger   setBit(int n)   우측에서 n+1번째 비트를 1로 변경
   BigInteger   clearBit(int n)   우측에서 n+1번째 비트를 0으로 변경
   BigInteger   flipBit(int n)   우측에서 n+1번째 비트를 전환(1→0, 0→1)

n의 값은 0부터 시작하므로, 우측에서 첫 번째 비트는 n이 0이다.

java.math.BigDecimal

실수를 정수와 10의 제곱의 곱으로 표현한다.

오차가 없는 2진 정수로 변환하여 다룬다.

정수 x 10-scale

scale은 0부터 Integer.MAX_VALUE사이의 범위에 있는 값.

정수를 저장하는 데 BitInteger를 사용한다.

따라서 BigDecimal도 불변이다.

private final BigInteger intVal;       // 정수Unscaled Value
private final int scale;               // 지수Scale
private transient int precision;       // 정밀도Precision

생성

기본형 리터럴로는 표현할 수 있는 값의 한계가 있어 일반적으로 문자열로 숫자를 표현한다.

BigDecimal bd;
bd = new BigDecimal("1234,56789");
bd = new BigDecimal(1234,56789);
bd = new BigDecimal(123456789);
bd = BigDecimal.valueOf(1234,56789);
bd = BigDecimal.valueOf(123456789);

double타입의 값을 매개변수로 갖는 생성자를 사용하면 오차가 발생할 수 있다.

Log.d("TAG_", new BigDecimal(0.1) + "");        // 0.1000000000000000055511151231257827021181583404541015625
Log.d("TAG_", new BigDecimal("0.1") + "");      // 0.1

다른 타입으로 변환

  • 문자열로 변환
String toPlainString()       // 어떤 경우에도 다른 기호 없이 숫자로만 표현
String toString()            // 필요하면 지수형태로 표현할 수 있음

    지수 형태의 리터럴을 사용했을 때 다른 결과를 얻는 경우가 있다.

BigDecimal bd = new BigDecimal(1.0e-22);
Log.d("TAG_", bd.toPlainString());      // 0.00000000000000000000010000000000000000485...
Log.d("TAG_", bd.toString());           // 1.00000000000000004859677432657087235297831...
  • Number로부터 상속받은 기본형으로 변환
int intValue()
long longValue()
float floatValue()
double doubleValue()
  • 정수형으로 변환하는 메서드 중 이름 끝에 Exact가 붙은 메서드

    변환한 결과가 변환한 타입의 범위에 속하지 않으면 ArithmeticException을 발생시킨다.

byte byteValueExact()
short shortValueExact()
int intValueExact()
long longValueExact()
BigInteger toBigIntegerExact()

연산

실수형에 사용할 수 있는 모든 연산자와 수학적인 계산을 쉽게 해주는 메서드들이 정의되어 있다.

BigDecimal add(BigDecimal val)         // this + val
BigDecimal subtract(BigDecimal val)    // this - val
BigDecimal multiply(BigDecimal val)    // this * val
BigDecimal divide(BigDecimal val)      // this / val
BigDecimal remainder(BigDecimal val)   // this % val

BigDecimal는 불변이므로, 새로운 인스턴스가 반환된다.

연산결과의 정수, 지수, 정밀도가 달라진다.

덧셈, 뺄셈에서는 둘 중에서 자리수가 높은 쪽으로 맞추기 위해서 두 scale 중에서 큰 쪽이 결과가 된다.

곱셈에서는 두 피연산자의 scale을 더하고, 나눗셈에서는 뺀다.

반올림 모드

나눗셈을 처리하기 위한 메서드가 다양하다.

나눗셈의 결과를 어떻게 반올림 처리(roundingMode)할 것인가, 몇 번째 자리(scale)에서 반올림할 것인지를 지정할 수 있다.

오차가 생길 수 있다.

BigDecimal divide(BigDecimal divisor)
BigDecimal divide(BigDecimal divisor, int roundingMode)
BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode)
BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
BigDecimal divide(BigDecimal divisor, MathContext mc)

roundingMode :  반올림 처리 방법에 대한 것. BigDecimal에 정의된 'ROUND_'로 시작하는 상수들 중 하나를 사용한다.

RoundingMode :  roundingMode를 열거형으로 정의한 것. 나중에 추가된 것으로, 가능하면 이것을 사용한다.

RoundingMode설명
   CEILING   올림
   FLOOR   내림
   UP   양수일 때는 올림, 음수일 때는 내림
   DOWN   양수일 때는 내림, 음수일 때는 올림
   HALF_UP   반올림 (5이상올림, 5미만 버림)
   HALF_EVEN   반올림 (반올림 자리의 값이 짝수면 HALF_DOWN, 홀수면 HALF_UP)
   HALF_DOWN   반올림 (6이상 올림, 6미만 버림)
   UNNECESSARY   나눗셈의 결과가 딱 떨어지는 수가 아니면, ArithmeticException 발생

divide()로 나눗셈한 결과가 무한소수인 경우, 반올림 모드를 지정해주지 않으면 ArithmeticException이 발생한다.

java.math.MathContext

반올림 모드와 정밀도를 하나로 묶어 놓은 것.

divide()에서는 scale이 소수점 이하의 자리수를 의미하는 것과 달리

정밀도precision가 정수와 소수점 이하를 모두 포함한 자리수를 의미한다.

scale의 변경

BigDecimal을 10으로 곱하거나 나누는 대신 scale의 값을 변경하여 같은 결과를 얻을 수 있다.

BigDecimal setScale(int newScale)
BigDecimal setScale(int newScale, int roundingMode)
BigDecimal setScale(int newScale, RoundingMode mode)

scale을 값을 줄이는 것은 10의 n제곱으로 나누는 것과 같다.

오차가 발생할 수 있고, 반올림 모드를 지정해주어야 한다.

참고 서적: 자바의 정석 3판