java.math

TIL·2023년 1월 11일
0

Java (최은빈)

목록 보기
21/27

BicInteger

  • int : 2,147,483,648 ~ 2,147,483,647
  • long : 9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
  • 숫자 범위가 이 범위를 넘는 경우 (특히 돈과 관련된 개발이나 알고리즘 문제 풀 때)
  • 무한한 정수가 들어갈 가능성이 있는 경우
final int signum; // 부호 (1 (양수), 0, -1 (음수))
final int[] mag; // 값 (magnitue) // 배열로 되어 있음

BigInteger
정수로 표현할 수 있는 값을 넘은 수를 다룰 경우

내부적으로는 int 배열을 사용해서 값을 다루기 때문에 long 타입보다 훨씬 큰 값을 다룰 수 있음
하지만 성능은 떨어짐
final 으로 되어있기 때문에 불변 (immutable)이고 다른 모든 정수형처럼 값을 2의 보수 형태로 저장


import java.math.BigInteger;
import java.util.Arrays;

public class BigIntegerExample {
    public static void main(String[] args) {

        //// BigInteger 생성
//        long longValue = 9223372036854775807; // stack over flow
        BigInteger bigInteger1 = new BigInteger("9223372036854775807");
        BigInteger bigInteger2 = new BigInteger("-9223372036854775807");
        BigInteger bigInteger3 = new BigInteger("FFFF", 16); // 16진수 저장 가능
        BigInteger bigInteger4 = BigInteger.valueOf(1234567890L); // Long 저장 가능
        System.out.println("bigInteger1 = " + bigInteger1);
        System.out.println("bigInteger1.signum() = " + bigInteger1.signum()); // 부호
        System.out.println("bigInteger2 = " + bigInteger2);
        System.out.println("bigInteger2.signum() = " + bigInteger2.signum());
        System.out.println("bigInteger3 = " + bigInteger3); // 65535
        System.out.println("bigInteger4 = " + bigInteger4); // 1234567890
        System.out.println();


        //// BigInteger ➡️️ 다른 타입
        // toString()
        String string1 = bigInteger1.toString();
        String string2 = bigInteger2.toString();
        String string3 = bigInteger3.toString();
        String string4 = bigInteger4.toString(16);
        System.out.println("string1 = " + string1);
        System.out.println("string2 = " + string2);
        System.out.println("string3 = " + string3);
        System.out.println("string4 = " + string4);
        System.out.println();

        // toByteArray() : int 배열 -> byte 배열
        byte[] bytes1 = bigInteger1.toByteArray();
        byte[] bytes2 = bigInteger2.toByteArray();
        byte[] bytes3 = bigInteger3.toByteArray();
        byte[] bytes4 = bigInteger4.toByteArray();
        // byte 배열 -> String
        System.out.println("bytes1 = " + Arrays.toString(bytes1));
        System.out.println("bytes2 = " + Arrays.toString(bytes2));
        System.out.println("bytes3 = " + Arrays.toString(bytes3));
        System.out.println("bytes4 = " + Arrays.toString(bytes4));
        System.out.println();

        // intValue()
        int intValue1 = bigInteger1.intValue();
        int intValue2 = bigInteger2.intValue();
        int intValue3 = bigInteger3.intValue();
        int intValue4 = bigInteger4.intValue();
        System.out.println("intValue1 = " + intValue1);
        System.out.println("intValue2 = " + intValue2);
        System.out.println("intValue3 = " + intValue3);
        System.out.println("intValue4 = " + intValue4);
        System.out.println();

        // longValue()
        long longValue1 = bigInteger1.longValue();
        long longValue2 = bigInteger2.longValue();
        long longValue3 = bigInteger3.longValue();
        long longValue4 = bigInteger4.longValue();
        System.out.println("longValue1 = " + longValue1);
        System.out.println("longValue2 = " + longValue2);
        System.out.println("longValue3 = " + longValue3);
        System.out.println("longValue4 = " + longValue4);
        System.out.println();

        // floatValue()
        float floatValue1 = bigInteger1.floatValue();
        float floatValue2 = bigInteger2.floatValue();
        float floatValue3 = bigInteger3.floatValue();
        float floatValue4 = bigInteger4.floatValue();
        System.out.println("floatValue1 = " + floatValue1);
        System.out.println("floatValue2 = " + floatValue2);
        System.out.println("floatValue3 = " + floatValue3);
        System.out.println("floatValue4 = " + floatValue4);
        System.out.println();

        // doubleValue()
        double doubleValue1 = bigInteger1.doubleValue();
        double doubleValue2 = bigInteger2.doubleValue();
        double doubleValue3 = bigInteger3.doubleValue();
        double doubleValue4 = bigInteger4.doubleValue();
        System.out.println("doubleValue1 = " + doubleValue1);
        System.out.println("doubleValue2 = " + doubleValue2);
        System.out.println("doubleValue3 = " + doubleValue3);
        System.out.println("doubleValue4 = " + doubleValue4);
        System.out.println();

        //// BigInteger 연산
        // 객체 이기 때문에 메서드 있다
        // add()
        BigInteger add1 = bigInteger1.add(bigInteger2);
        BigInteger add2 = bigInteger3.add(bigInteger4);
        System.out.println("add1 = " + add1);
        System.out.println("add2 = " + add2);

        // subtract()
        BigInteger sub1 = bigInteger1.subtract(bigInteger2);
        BigInteger sub2 = bigInteger3.subtract(bigInteger4);
        System.out.println("sub1 = " + sub1);
        System.out.println("sub2 = " + sub2);

        // multiply()
        BigInteger mul1 = bigInteger1.multiply(bigInteger2);
        BigInteger mul2 = bigInteger3.multiply(bigInteger4);
        System.out.println("mul1 = " + mul1);
        System.out.println("mul2 = " + mul2);

        // divide()
        BigInteger div1 = bigInteger1.divide(bigInteger2);
        BigInteger div2 = bigInteger3.divide(bigInteger4);
        System.out.println("div1 = " + div1);
        System.out.println("div2 = " + div2);

        // remainder() : 나머지
        BigInteger remainder1 = bigInteger1.remainder(bigInteger2);
        BigInteger remainder2 = bigInteger3.remainder(bigInteger4);
        System.out.println("remainder1 = " + remainder1);
        System.out.println("remainder2 = " + remainder2);
        System.out.println();


        //// BigInteger 비트 연산 메서드
        BigInteger bigInteger = new BigInteger("11");
        System.out.println("bigInteger.toString(2) = " + bigInteger.toString(2));
        System.out.println("bigInteger.toString(2) = " + bigInteger.toString(8));
        System.out.println("bigInteger.toString(2) = " + bigInteger.toString(16));

        // bitCount()
        // bitLength()
        int numOfOne = bigInteger.bitCount();
        int numOfZero = bigInteger.bitLength() - numOfOne;
        System.out.println("numOfOne = " + numOfOne);
        System.out.println("numOfZero = " + numOfZero);

        // testBit()
        boolean testBit = bigInteger.testBit(2);
        System.out.println("testBit = " + testBit);
        // val: 1 0 1 1
        // idx: 3 2 1 0

        // setBit()
        BigInteger setBit  = bigInteger.setBit(2);
        System.out.println("setBit = " + setBit);

        // clearBit()
        BigInteger clearBit = bigInteger.clearBit(1);
        System.out.println("clearBit = " + clearBit);

        // flipBit()
        BigInteger flipBit = bigInteger.flipBit(2);
        System.out.println("flipBit = " + flipBit);
        System.out.println();
        System.out.println();


        //// factorial 테스트
        for (int i = 0; i < 100; i++) {
            System.out.printf("factorial(%d) = %d \n", i, factorial(i));
            System.out.printf("factorial(%d) = %d \n", i, factorial(new BigInteger(Integer.toString(i))));
            System.out.println();
        }

    }
    public static BigInteger factorial(BigInteger n) { // n! = 1 x 2 x 3 x 4 x ... n
        if (n == null) return BigInteger.ZERO;

        if (n.equals(BigInteger.ZERO)) return BigInteger.ONE;
        else return n.multiply(factorial(n.subtract(BigInteger.ONE))); // n * factorial(n-1)
    }

    public static long factorial(long n) { // n! = 1 x 2 x 3 x 4 x ... n (20! 까지 가능)
        if (n == 0) return 1;
        else return n * factorial(n-1); // n * factorial(n-1)
    }
}



BicDecimal

  • double 타입으로 표현할 수 있는 값은 범위가 넓지만 정밀도가 최대 13자리 밖에 되지 않음
  • 실수형 특성상 오차를 피할 수 없다는 단점이 있음
  • BigDecimal은 실수형과 달리 정수를 이용해서 실수 표현
  • 실수의 오차는 10진 실수를 2진 실수로 정확하게 표현할 수 없는 경우가 있기 때문에 발생하는 것으로 오차가 없는 2진 정수로 변환해서 다룸
  • 실수와 정수롤 10의 제곱의 곱으로 표현
    • 정수 x 10^(-scale), scale - 0 ~ Integer.MAX_VALUE
private final BigInteger intVal; // 정수 (unscaled value) // int형 배열 사용
private final int scale; // 지수 (scale)
private transient int precision; // 정밀도 (precision) 정수의 자리수

// (cf) transient: Serialize하는 과정에 제외하고 싶은 변수 앞에 선언함 (보안상의 이유로)
//               : 필드는 유지되지만 null로 초기화됨
//               : 데이터 제외시 서비스 장애 이상이 없는지 고려해서 제외해야 함
  • BigDecimal(”123.45”) → 12345 x 10^(-2)로 표현
    • intVal - 12345
    • scale - 2
    • precision - 5

BigDecimal: 정수를 이용해서 실수를 표현
private final BigInteger intVal; // 정수 (unscaled value)
private final int scale; // 지수 (scale)
private transient int precision; // 정밀도 (precision) 정수의 자리수
(cf) transient: Serialize하는 과정에 제외하고 싶은 변수 앞에 선언함 (보안상의 이유로)
: 필드는 유지되지만 null로 초기화됨
: 데이터 제외시 서비스 장애 이상이 없는지 고려해서 제외해야 함

실수의 오차는 10진 실수를 2진 실수로 정확히 변환할 수 없는 경우가 있기 때문에 발생하는 것임
오차가 없는 2진 정수로 변환해서 다룰 수 있음 => 정수 x 10^(-scale)

final 으로 되어있기 때문에 불변 (immutable)임
BigDecimal은 정수를 저장하는데 BigInteger을 사용함

import 해야함

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;

public class BigDecimalExample {
    public static void main(String[] args) {

        //// BigDecimal 분석
        double doubleValue1 = 123.45;
        System.out.println("doubleValue1 = " + doubleValue1);

        BigDecimal bigDecimal1 = new BigDecimal("123.45"); // 12345 x 10^(-2)
        System.out.println("bigDecimal1 = " + bigDecimal1);

        // unscaledValue(), scale(), precision()
        System.out.println("bigDecimal1.unscaledValue() = " + bigDecimal1.unscaledValue()); // 12345
        System.out.println("bigDecimal1.scale() = " + bigDecimal1.scale()); // 2
        System.out.println("bigDecimal1.precision() = " + bigDecimal1.precision()); // 5
        System.out.println();

        // 소수점 아래 14자리까지만 표현됨
        double doubleValue2 = 123.45123124123123123123123123; // 실수가 길면 부동 소수점에 의해 잘림
        System.out.println("doubleValue2 = " + doubleValue2);
        BigDecimal bigDecimal2 = new BigDecimal("123.45123124123123123123123123"); // 12345 x 10^(-2) // 정확
        System.out.println("bigDecimal2 = " + bigDecimal2);

        System.out.println("bigDecimal2.unscaledValue() = " + bigDecimal2.unscaledValue());
        System.out.println("bigDecimal2.scale() = " + bigDecimal2.scale());
        System.out.println("bigDecimal2.precision() = " + bigDecimal2.precision());
        System.out.println();


        //// BigDecimal 생성 => "" 으로 생성 (데이터의 손상 없도록)
        BigDecimal bigDecimal3 = new BigDecimal("123.4567890"); // "" 으로 생성
        BigDecimal bigDecimal4 = new BigDecimal(123.4567890); // 그냥 double로 생성하면 부동 소수점에 의해 부정확
        BigDecimal bigDecimal5 = new BigDecimal(1234567890);

        // 만약 double을 인자로 주고 싶을 경우 valueOf() 사용
        BigDecimal bigDecimal6 = BigDecimal.valueOf(123.4567890);
        BigDecimal bigDecimal7 = BigDecimal.valueOf(1234567890);

        System.out.println("bigDecimal3 = " + bigDecimal3);
        System.out.println("bigDecimal4 = " + bigDecimal4);
        System.out.println("bigDecimal5 = " + bigDecimal5);
        System.out.println("bigDecimal6 = " + bigDecimal6);
        System.out.println("bigDecimal7 = " + bigDecimal7);
        System.out.println();


        //// BigDecimal ➡️️ String
        // toString()
        // toPlainString()
        // toEngineeringString()
        BigDecimal bigDecimal8 = new BigDecimal(1.0e-30); // 지수를 이용해서 초기화 가능
        String string1 = bigDecimal8.toString(); // 생성자로 전달받은 값 그대로 반환
        String plainString1 = bigDecimal8.toPlainString(); // 생성자로 전달받은 값을 지수표현없이 반환
        String engineerString1 = bigDecimal8.toEngineeringString(); // 지수표현이 있으면 엔지니어링 표기법으로 반환 (거듭제곱이 3의 배수)
        System.out.println("string1         = " + string1);
        System.out.println("plainString1    = " + plainString1);
        System.out.println("engineerString1 = " + engineerString1);
        System.out.println();

        BigDecimal bigDecimal9 = new BigDecimal(0.0001e-20); // 지수를 이용해서 초기화 가능
        String string2 = bigDecimal9.toString(); // 생성자로 전달받은 값 그대로 반환
        String plainString2 = bigDecimal9.toPlainString(); // 생성자로 전달받은 값을 지수표현없이 반환
        String engineerString2 = bigDecimal9.toEngineeringString(); // 지수표현이 있으면 엔지니어링 표기법으로 반환 (거듭제곱이 3의 배수)
        System.out.println("string2         = " + string2);
        System.out.println("plainString2    = " + plainString2);
        System.out.println("engineerString2 = " + engineerString2);
        System.out.println();


        //// BigDecimal ➡️️ 다른 타입
        // valueOf()
        BigDecimal bigDecimal10 = new BigDecimal("123.45123124123123123123123123");
        BigDecimal bigDecimal11 = new BigDecimal(123.45123124123123123123123123); // BigDecimal(double)은 double가 부정확하기 때문에 예측 불가
        BigDecimal bigDecimal12 = new BigDecimal(1234567890);
        BigDecimal bigDecimal13 = BigDecimal.valueOf(123.45123124123123123123123123); // 만약 double을 인자로 주고 싶을 경우 valueOf(double) 사용
        BigDecimal bigDecimal14 = BigDecimal.valueOf(1234567890);
        System.out.println("bigDecimal10 = " + bigDecimal10);
        System.out.println("bigDecimal11 = " + bigDecimal11);
        System.out.println("bigDecimal12 = " + bigDecimal12);
        System.out.println("bigDecimal13 = " + bigDecimal13);
        System.out.println("bigDecimal14 = " + bigDecimal14);
        System.out.println();

        // byteValue()
        byte byte10 = bigDecimal10.byteValue();
        byte byte11 = bigDecimal11.byteValue();
        byte byte12 = bigDecimal12.byteValue();
        byte byte13 = bigDecimal13.byteValue();
        byte byte14 = bigDecimal14.byteValue();
        System.out.println("byte10 = " + byte10);
        System.out.println("byte11 = " + byte11);
        System.out.println("byte12 = " + byte12);
        System.out.println("byte13 = " + byte13);
        System.out.println("byte14 = " + byte14);
        System.out.println();

        // intValue()
        int intValue10 = bigDecimal10.intValue();
        int intValue11 = bigDecimal11.intValue();
        int intValue12 = bigDecimal12.intValue();
        int intValue13 = bigDecimal13.intValue();
        int intValue14 = bigDecimal14.intValue();
        System.out.println("intValue10 = " + intValue10);
        System.out.println("intValue11 = " + intValue11);
        System.out.println("intValue12 = " + intValue12);
        System.out.println("intValue13 = " + intValue13);
        System.out.println("intValue14 = " + intValue14);
        System.out.println();

        // longValue()
        long longValue10 = bigDecimal10.longValue();
        long longValue11 = bigDecimal11.longValue();
        long longValue12 = bigDecimal12.longValue();
        long longValue13 = bigDecimal13.longValue();
        long longValue14 = bigDecimal14.longValue();
        System.out.println("longValue10 = " + longValue10);
        System.out.println("longValue11 = " + longValue11);
        System.out.println("longValue12 = " + longValue12);
        System.out.println("longValue13 = " + longValue13);
        System.out.println("longValue14 = " + longValue14);
        System.out.println();

        // floatValue()
        float floatValue10 = bigDecimal10.floatValue();
        float floatValue11 = bigDecimal11.floatValue();
        float floatValue12 = bigDecimal12.floatValue();
        float floatValue13 = bigDecimal13.floatValue();
        float floatValue14 = bigDecimal14.floatValue();
        System.out.println("floatValue10 = " + floatValue10);
        System.out.println("floatValue11 = " + floatValue11);
        System.out.println("floatValue12 = " + floatValue12);
        System.out.println("floatValue13 = " + floatValue13);
        System.out.println("floatValue14 = " + floatValue14);
        System.out.println();

        // doubleValue()
        double doubleValue10 = bigDecimal10.doubleValue();
        double doubleValue11 = bigDecimal11.doubleValue();
        double doubleValue12 = bigDecimal12.doubleValue();
        double doubleValue13 = bigDecimal13.doubleValue();
        double doubleValue14 = bigDecimal14.doubleValue();
        System.out.println("doubleValue10 = " + doubleValue10);
        System.out.println("doubleValue11 = " + doubleValue11);
        System.out.println("doubleValue12 = " + doubleValue12);
        System.out.println("doubleValue13 = " + doubleValue13);
        System.out.println("doubleValue14 = " + doubleValue14);
        System.out.println();

        // toBigInteger()
        BigInteger bigInteger10 = bigDecimal10.toBigInteger();
        BigInteger bigInteger11 = bigDecimal11.toBigInteger();
        BigInteger bigInteger12 = bigDecimal12.toBigInteger();
        BigInteger bigInteger13 = bigDecimal13.toBigInteger();
        BigInteger bigInteger14 = bigDecimal14.toBigInteger();
        System.out.println("bigInteger10 = " + bigInteger10);
        System.out.println("bigInteger11 = " + bigInteger11);
        System.out.println("bigInteger12 = " + bigInteger12);
        System.out.println("bigInteger13 = " + bigInteger13);
        System.out.println("bigInteger14 = " + bigInteger14);
        System.out.println();


        //// BigDecimal 연산
        // add, subtract, multiply, divide, remainder
        BigDecimal bigDecimal15 = new BigDecimal("123.456");
        BigDecimal bigDecimal16 = new BigDecimal("0.1");
        BigDecimal add = bigDecimal15.add(bigDecimal16);
        BigDecimal sub = bigDecimal15.subtract(bigDecimal16);
        BigDecimal mul = bigDecimal15.multiply(bigDecimal16);
        BigDecimal div = bigDecimal15.divide(bigDecimal16);
        BigDecimal remainder = bigDecimal15.remainder(bigDecimal16);
        System.out.println("bigDecimal15 = " + bigDecimal15 + ", bigDecimal15.unscaledValue() = " +
                bigDecimal15.unscaledValue() + ", bigDecimal15.scale() = " + bigDecimal15.scale() + ", bigDecimal15.precision() = " + bigDecimal15.precision());
        System.out.println("bigDecimal16 = " + bigDecimal16 + ", bigDecimal16.unscaledValue() = " +
                bigDecimal16.unscaledValue() + ", bigDecimal16.scale() = " + bigDecimal16.scale() + ", bigDecimal16.precision() = " + bigDecimal16.precision());
        System.out.println("=============================================================================================================");
        System.out.println("add = " + add + ", add.unscaledValue() = " + add.unscaledValue() + ", add.scale() = " + add.scale() + ", add.precision() = " + add.precision());
        System.out.println("sub = " + sub + ", sub.unscaledValue() = " + sub.unscaledValue() + ", sub.scale() = " + sub.scale() + ", sub.precision() = " + sub.precision());
        System.out.println("mul = " + mul + ", mul.unscaledValue() = " + mul.unscaledValue() + ", mul.scale() = " + mul.scale() + ", mul.precision() = " + mul.precision());
        System.out.println("div = " + div + ", div.unscaledValue() = " + div.unscaledValue() + ", div.scale() = " + div.scale() + ", div.precision() = " + div.precision());
        System.out.println("remainder = " + remainder + ", remainder.unscaledValue() = " + remainder.unscaledValue() + ", remainder.scale() = " + remainder.scale() + ", remainder.precision() = " + remainder.precision());
        System.out.println();


        // 반올림 모드 (divide(), setScale())
        // roundingMode - 나눗셈 결과 어떻게 반올림 할 것인가
        // - CEILING: 올림
        // - FLOOR: 내림
        // - UP: 양수일 때는 올림, 음수일 때는 내림
        // - DOWN: 양수일 때는 내림, 음수일 때는 내림
        // - HALF_UP: 반올림 (5이상 올림, 5미만 버림)
        // - HALF_EVEN: 반올림 (반올림 자리의 값이 짝수면 HALF_DOWN, 홀수면 HALF_UP)
        // - HALF_DOWN: 반올림 (6이상 올림, 6미만 버림)
        // - UNNECESSARY: 나눗셈 결과가 딱 떨어지는 수가 아니면 ArithmeticException 발생
        // (*) divide()한 나눗셈 결과가 무한 소수인 경우, 반올림 모드를 지정해주지 않으면 ArithmeticException 발생
        BigDecimal bigDecimal17 = new BigDecimal("123.4567890");
        BigDecimal bigDecimal18 = new BigDecimal("0.1");
        System.out.println("bigDecimal17 = " + bigDecimal17);
        System.out.println("bigDecimal18 = " + bigDecimal18);
        BigDecimal divide1 = bigDecimal17.divide(bigDecimal18, 2, RoundingMode.HALF_UP); // 정밀도 2에서 반올림
        BigDecimal divide2 = bigDecimal17.divide(bigDecimal18, new MathContext(2, RoundingMode.HALF_UP)); // 정밀도 2에서 반올림
        System.out.println("divide1 = " + divide1);
        System.out.println("divide2 = " + divide2.toPlainString());


    }
}

0개의 댓글

관련 채용 정보