🌺 BigInteger / BigDecimal Class

배효림·2023λ…„ 4μ›” 4일
0

μŠ€ν„°λ””

λͺ©λ‘ 보기
1/3

βœ” BigInteger : μ •μˆ˜ν˜•μ„ λ„˜μ–΄κ°€λŠ” 값을 μ²˜λ¦¬ν•˜λŠ” 문제

intint , longlong ν˜•μ„ λ„˜μ–΄κ°€λŠ” 연산에 λŒ€ν•΄ μ–΄λ–»κ²Œ μ²˜λ¦¬ν•˜λŠ” 것이 μ’‹μ„κΉŒ? κ°€μž₯ 큰 μ •μˆ˜ν˜• νƒ€μž…μΈ longlong 은 10μ§„μˆ˜λ‘œ 19μžλ¦¬μ΄λ‹€. ν•˜μ§€λ§Œ, 가끔 이보닀 더 큰 값을 닀뀄야 ν•  λ•Œκ°€ μžˆλ‹€. 이럴 λ•ŒλŠ” μ•„λž˜μ™€ 같이,

  1. λ§Œμ•½ λ¬Έμ œμ—μ„œ modmod 연산을 ν•˜λΌκ³  ν•˜κ±°λ‚˜, 닡을 일정 숫자둜 λ‚˜λˆ„λΌκ³  ν•œλ‹€λ©΄, λ‚˜λ¨Έμ§€ (%) 연산을 톡해 μ—°μ‚° 쀑간 쀑간에 값을 보정해쀀닀
  2. BigInteger 클래슀λ₯Ό μ‚¬μš©ν•œλ‹€.

두 κ°€μ§€μ˜ 방법이 μžˆλ‹€. 이 λ¬Έμ„œμ—μ„œλŠ” 두 번째 방법인 BigInteger 클래슀, 그리고 μ†Œμˆ«μ  계산에 λŒ€ν•΄ λΉ„μŠ·ν•œ μˆ˜ν–‰μ„ ν•˜λŠ” BigDecimal ν΄λž˜μŠ€μ— λŒ€ν•΄ μ‚΄νŽ΄λ³Έλ‹€.

❔ λ‚΄λΆ€μ μœΌλ‘œ μ–΄λ–»κ²Œ κ΄€λ¦¬ν•˜λŠ”κ°€ ?

BigInteger ν΄λž˜μŠ€λŠ” λ‚΄λΆ€μ μœΌλ‘œ int λ°°μ—΄μ˜ ν˜•νƒœλ‘œ 이루어져 있기 λ•Œλ¬Έμ— long νƒ€μž…λ³΄λ‹€ 훨씬 큰 값을 ν‘œν˜„ν•  수 μžˆλ‹€. 10μ§„μˆ˜λ‘œλŠ” 10의 6μ–΅ μ œκ³±λ§ŒνΌμ„ ν‘œν˜„ν•  수 μžˆλ‹€.

 final int signum;	// λΆ€ν˜Έ 
 final int[] mag;	// κ°’ 

🌺 생성 방법

  1. λ¬Έμžμ—΄λ‘œ 생성
BigInteger num = new BigInteger("123");
  1. nμ§„μˆ˜μ˜ λ¬Έμžμ—΄λ‘œ 생성
BigInteger num = new BigInteger("FFFF", 16);
  1. 숫자둜 생성
BigInteger num = BigInteger.valueOf(123L);

🌺 κΈ°λ³Έ μ—°μ‚° 방법

λ‚΄λΆ€μ μœΌλ‘œ Integer 으둜 ν•  수 μžˆλŠ” λͺ¨λ“  μ—°μ‚°μžμ™€ λ”λΆˆμ–΄ modmod μ—°μ‚°, GCDGCD μ—°μ‚°, μ†Œμˆ˜νŒλ³„ λ“± μΆ”κ°€μ μœΌλ‘œ μœ μš©ν•œ λ©”μ†Œλ“œλ₯Ό μ œκ³΅ν•œλ‹€.


 BigInteger test0 =  BigInteger.valueOf(1);
 BigInteger test1 = test0.add(new BigInteger("2")); 		// 3
 BigInteger test2 = test0.subtract(new BigInteger("2")); 	// -1
 BigInteger test3 = test0.multiply(new BigInteger("2")); 	// 2
 BigInteger test4 = test0.divide(new BigInteger("2")); 		// 0
 BigInteger test4 = test0.remainder(new BigInteger("2")); 	// 1 

μœ„μ˜ μ½”λ“œμ—μ„œ κ°„λ‹¨ν•œ 사칙연산 예제λ₯Ό λ‹€λ£¨λŠ”λ°, μΆ”κ°€μ μœΌλ‘œ String 처럼 Immutable ν•˜λ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. κ·Έ 말은 μ¦‰μŠ¨, ν•œ 번 μΈμŠ€ν„΄μ‹± 되고 λ‚˜λ©΄ κ·Έ 값을 λ°”κΏ€μˆ˜κ°€ μ—†κ³ , μ—°μ‚° λ°˜ν™˜ νƒ€μž…μœΌλ‘œ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€κ°€ λ°˜ν™˜λœλ‹€.

🌺 λΉ„νŠΈ μ—°μ‚° 방법

AndAnd, oror, xorxor , notnot κ³Ό 같은 κΈ°λ³Έ λΉ„νŠΈ μ—°μ‚° 이외에도 λΉ„νŠΈ κ΄€λ ¨ν•΄μ„œ μœ μš©ν•œ λ©”μ†Œλ“œλ₯Ό 많이 μ œκ³΅ν•œλ‹€. λ‹Ήμ—°ν•˜κ²Œλ„ longlong 연산보닀 μ‹œκ°„μ΄ 였래 걸리기 λ•Œλ¬Έμ— μ•„λž˜μ˜ λ©”μ†Œλ“œλ“€μ„ 잘 ν™œμš©ν•˜λ©΄ μ„±λŠ₯ ν–₯상에 도움이 λœλ‹€.

  1. int bitCount() : 2μ§„μˆ˜λ‘œ ν‘œν˜„ν–ˆμ„ λ•Œ μ–‘μˆ˜λŠ” 1의 개수, μŒμˆ˜λŠ” 0의 개수λ₯Ό λ°˜ν™˜
  2. int bitLength() : 2μ§„μˆ˜λ‘œ ν‘œν˜„ν–ˆμ„ λ•Œ ν•„μš”ν•œ λΉ„νŠΈ 수
  3. boolean testBit(int n) : μš°μΈ‘μ—μ„œ n+1번째 λΉ„νŠΈκ°€ 1인지에 λŒ€ν•œ μ—¬λΆ€
  4. boolean setBit(int n) : μš°μΈ‘μ—μ„œ n+1번째 λΉ„νŠΈλ₯Ό 1둜 λ³€κ²½
  5. boolean clearBit(int n) : μš°μΈ‘μ—μ„œ n+1번째 λΉ„νŠΈλ₯Ό 0둜 λ³€κ²½
  6. boolean flipBit(int n) : μš°μΈ‘μ—μ„œ n+1번째 λΉ„νŠΈλ₯Ό 0<->1둜 λ³€κ²½
 BigInteger num =  BigInteger.valueOf(4);   // 100
 int oneCount = num.bitCount();				// 1
 int bitLength = num.bitLength();			// 3
 boolean IsOne = num.testBit(2);			// true

예둜 λ“€μ–΄, BigInteger κ°€ μ§μˆ˜μž„μ„ ν™•μΈν•˜λ €λ©΄ 제일 λ§ˆμ§€λ§‰ λΉ„νŠΈκ°€ 0인지 testBit(0)둜 확인을 ν•˜λŠ” 것이 λ‚˜λ¨Έμ§€ 연산을 ν•˜λŠ” 것보닀 효율적일 것이닀.

🌺 λ‹€λ₯Έ νƒ€μž…μœΌλ‘œ λ³€ν™˜ 방법

  1. λ¬Έμžμ—΄ λ˜λŠ” byteArray 둜 λ³€ν™˜
 BigInteger num =  BigInteger.valueOf(4);
 String numStr = num.toString(); 			// "4"
 String numStr2 = num.toString(2);   		// "110"
  1. primitive type 으둜 λ³€ν™˜
 BigInteger num =  BigInteger.valueOf(4);
 int intNum = num.intValue(); 				// 4
 int intNum2 = num.intValueExact(); 		// 4

단, primitive type 으둜 λ³€ν™˜ν•˜λŠ” λ©”μ†Œλ“œ 쀑 suffix둜 Exactκ°€ 뢙은 λ©”μ†Œλ“œλ“€μ€, 맀개 λ³€μˆ˜κ°€ ν•΄λ‹Ή μžλ£Œν˜•μ˜ λ²”μœ„λ₯Ό λ„˜μ–΄κ°ˆ μ‹œ, ArithmeticException 을 λ°œμƒμ‹œν‚¨λ‹€.

βœ” BigDecimal : μ†Œμˆ«μ  정밀도 문제

μ•žμ„œ μ‚΄νŽ΄λ³Έ BigInteger ν΄λž˜μŠ€λŠ” μ •μˆ˜ν˜•μ˜ λ²”μœ„λ₯Ό λ„˜μ–΄κ°€λŠ” 값에 λŒ€ν•œ ν‘œν˜„ 및 연산을 ν•  λ•Œ μ‚¬μš©ν–ˆλ‹€. λΉ„μŠ·ν•˜κ²Œ BigDecimal ν΄λž˜μŠ€λŠ” double 의 정밀도(13자리)보닀 더 μ •ν™•ν•˜κ²Œ 값을 ν‘œν˜„ν•΄μ•Ό ν•  λ•Œ μ“΄λ‹€.

private final BigInteger intVal;			// μ •μˆ˜
private final int scale;  					// μ†Œμˆ«μ  μ΄ν•˜μ˜ 자리수
private transient int precision;			// μ •μˆ˜ μ „μ²΄μ˜ 자릿수

λ‚΄λΆ€μ μœΌλ‘œλŠ” μœ„μ™€ 같이 κ΅¬μ„±λ˜μ–΄ μžˆλ‹€. 예둜 λ“€μ–΄μ„œ, 12.34 λΌλŠ” 값을 BigDecimal 둜 μΈμŠ€ν„΄μ‹±ν•œλ‹€λ©΄,

  • intVal : 1234
  • scale : 2
  • precision : 4

μ΄λ ‡κ²Œ λ“€μ–΄κ°ˆ 것이닀. 내뢀적인 μš”μ†Œλ₯Ό μ•„λŠ” 것은 μ—°μ‚° νš¨μœ¨μ„±μ„ μ˜¬λ¦¬λŠ” 것에도 도움이 λœλ‹€. 예둜 λ“€μ–΄μ„œ, μ–΄λ– ν•œ μ†Œμˆ˜λ₯Ό 10으둜 λ‚˜λˆˆλ‹€κ³  μƒκ°ν•΄λ³΄μž. Divide 연산을 μ‚¬μš©ν•˜λŠ” 것보닀 setScale ν•¨μˆ˜λ₯Ό 톡해 scale을 1 λŠ˜λ¦¬λŠ” 것이 더 νš¨μœ¨μ μ΄λ‹€.

🌺 생성 방법

  1. λ¬Έμžμ—΄λ‘œ 생성
BigDecimal num = new BigDecimal("1.23");
  1. κΈ°λ³Έ νƒ€μž… 숫자둜 생성
BigDecimal num = new BigDecimal(1.23); 	// Unpredictable
BigDecimal num2 = BigDecimal.valueOf(1.23);	// κ°€λŠ₯ν•œ μ΄λ ‡κ²Œ μƒμ„±ν•˜μž! 
  1. μ§€μˆ˜ ν˜•νƒœμ˜ λ¦¬ν„°λŸ΄λ‘œ 생성
BigDecimal dc = new BigDecimal(1.0e-22); // Unpredictable

2와 3번의 μ£Όμ˜ν•  점은 BigInteger μ™€λŠ” λ‹€λ₯΄κ²Œ κΈ°λ³Έ νƒ€μž… 숫자둜 생성할 수 μžˆμ§€λ§Œ, ν•΄λ‹Ή 값이 μ •ν™•ν•˜κ²Œ λ“€μ–΄κ°ˆ μ§€λŠ” 아무도 λͺ¨λ₯Έλ‹€. 예둜 λ“€μ–΄μ„œ 1.23 을 λ„£μ—ˆλŠ”λ° 1.230000000000000000013515 μ΄λŸ°μ‹μ˜ μ˜λ„μΉ˜ μ•Šμ€ 값이 λ“€μ–΄κ°ˆ 수 μžˆλ‹€.

🌺 μ—°μ‚° 방법

μ‹€μˆ˜ν˜•μ—μ„œ ν•  수 μžˆλŠ” 기본적인 연산을 BigDecimal ν΄λž˜μŠ€μ—μ„œλ„ ν•  수 μžˆλ‹€. μ—°μ‚° 결과에 따라, 정밀도λ₯Ό ν—€μΉ˜μ§€ μ•Šκ²Œ intVal, Scale, Precision 이 μ—…λ°μ΄νŠΈ λœλ‹€. 예둜 λ“€μ–΄μ„œ λΊ„μ…ˆμ„ ν•œλ‹€λ©΄ 두 ν”Όμ—°μ‚°μž 쀑 μžλ¦¬μˆ˜κ°€ 높은 μͺ½μ˜ scale 을 μ‚¬μš©ν•˜κ²Œ λœλ‹€.

BigDecimal test0 = new BigDecimal("1.1");
BigDecimal test1 = test0.add(new BigDecimal("0.05"));		// 1.15
BigDecimal test2 = test0.subtract(new BigDecimal("0.05"));	// 1.05
BigDecimal test3 = test0.multiply(new BigDecimal("2"));		// 2.2

λ‚˜λˆ—μ…ˆμ„ μ²˜λ¦¬ν•˜κΈ° μœ„ν•œ λ©”μ†Œλ“œλŠ” λ‹€μ–‘ν•˜κ²Œ μžˆλŠ”λ°, μ–΄λ–»κ²Œ 반올림 ν•  것인지, λͺ‡λ²ˆμ§Έ μžλ¦¬μ—μ„œ ν•  것인지λ₯Ό 지정할 수 μžˆλ‹€.

  1. divide(BigDecimal divisor) : κΈ°λ³Έ λ‚˜λˆ—μ…ˆ
  2. divide(BigDecimal divisor, RoundingMode roundingMode) : 반올림 처리 방법 지정 κ°€λŠ₯ν•œ λ‚˜λˆ—μ…ˆ
  3. divide(BigDecimal divisor, int scale, RoundingMode roundingMode) : λͺ‡λ²ˆμ§Έ μžλ¦¬μ—μ„œ μ–΄λ–»κ²Œ λ°˜μ˜¬λ¦Όμ„ μ²˜λ¦¬ν•  것인지 지정 κ°€λŠ₯ν•œ λ‚˜λˆ—μ…ˆ
BigDecimal test0 = new BigDecimal("10.1");
BigDecimal test1 = test0.divide(BigDecimal.valueOf(10), RoundingMode.CEILING);
BigDecimal test2 = test0.divide(BigDecimal.valueOf(10), RoundingMode.FLOOR);
BigDecimal test3 = test0.divide(BigDecimal.valueOf(10), RoundingMode.HALF_UP);

BigDecimal test4 = new BigDecimal("10");
BigDecimal test5 = test4.divide(BigDecimal.valueOf(10), RoundingMode.UNNECESSARY);

CEILING 은 올림, FLOOR 은 λ‚΄λ¦Ό, HALF_UP 은 5이상 올림 5미만 버림, 그리고 UNNECESSARY λŠ” λ‚˜λˆ—μ…ˆμ˜ κ²°κ³Όκ°€ λ”± 떨어지지 μ•ŠμœΌλ©΄ μ—λŸ¬λ₯Ό λ°˜ν™˜ν•œλ‹€. 이 외에도, 반올림의 자리 값이 μ§μˆ˜μΈμ§€ ν™€μˆ˜μΈμ§€, 6이상 올림 6미만 버림 λ“±μ˜ RoundingMode κ°€ μ‘΄μž¬ν•œλ‹€.

profile
항상 μœ„λ₯Ό λ°”λΌλ³΄λŠ” ν”„λ‘œκ·Έλž˜λ¨Έ

0개의 λŒ“κΈ€