알고리즘/알고리즘(Java)

12. [수치] 진수 변환

산을좋아한라쯔 2015. 4. 2. 22:29
반응형

[문제]

큰 자릿수의 정수가 아래와 같이 byte형 배열로 표현될 때, 이 큰 정수를 2진수, 16진수의 배열로 표현하시오.

ex1) a = {0x11,0x22} 일 때,

    a_2 = {1 ,0,0,0,1,0,0,1,0,0,0,1,0,}    

    a_16 = {11,22}

ex2)a={0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11}

    a_2 = ...

    

    a_16 = {88,77,66,55,44,33,22,11}


[풀이]

변환해야할 정수의 크기가, 프로그래밍 언어에서 지원하는 기본 변수형태에서 커버 가능하다면, 진수의 변환 문제는 그리 큰 고민이 아니다. 

자바에서 정수를 다룰 수 있는 가장 큰 변수형태는 long이고, long변수에는 8바이트 메모리가 할당 되고 양수/음수 둘 다 지원하므로, long타입 변수에서 표현할 수 있는 정수의 범위는 -2^63 ~ (2^63 + 1) 까지이다. 이 범위내에서의 문제라면 아래와 같이 하면 된다.

long a = 0x1122;

String str = Long.toBinaryString(a)


근데, 8바이트를 넘어가는 수이고, 수가 배열로 주어지면?

이 때는 배열값의 연산을 통해 원하는 진수(2진수 혹은 2^n 진수)로 아래와 같이 변환할 수 있다.


2진수로의 변환

a_2[0] = (a[0] >>> 7) & 0x01;

a_2[2] = (a[0] >>> 6) & 0x01;

a_2[3] = (a[0] >>> 5) & 0x01;

...

a_2[7] = (a[0] >>> 0) & 0x01;

a_2[8] = (a[1] >>> 7) & 0x01;

a_2[9] = (a[1] >>> 6) & 0x01;

a_2[10] = (a[1] >>> 5) & 0x01;

...

a_2[14] = (a[1] >>> 0) & 0x01;

...


규칙성이 보이는가?
2진수의 경우는, 원래의 8비트짜리 값에 대해 8개의 이진수가 나오므로, 이진수로 나타낼 각 비트값을 오른쪽 끝으로 shift한 후, 0x01과의 비트연산을 통해서 0인지 1인지 판단 

16진수로의 변환
a_16[0] = (a[0] >>> 4) & 0x0f;
a_16[1] = (a[0] >>> 0) & 0x0f;
a_16[2] = (a[1] >>> 4) & 0x0f;
a_16[3] = (a[1] >>> 0) & 0x0f;

...



[소스코드]

package p3;

 

public class ConvertDigit {

         public ConvertDigit() {

                  test();

         }       

        

         private void test() {

                  byte[] a, a_2, a_16;

 

                  a = new byte[] { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, (byte) 0xaa, (byte) 0x99 };

 

                  a_2 = convert(a, (byte) 2);

                  a_16 = convert(a, (byte) 16);

                 

                 

                  for(int i=0;i<a_2.length;i++){

                           System.out.print(a_2[i]);

                  }                

                  System.out.println("");

                 

                  for(int i=0;i<a_16.length;i++){

                           System.out.print(a_16[i]);

                  }

                 

         }

 

         private byte[] convert(byte[] a, byte radix) throws IllegalArgumentException {

                  byte[] a_x = null;

 

                  switch (radix) {

                  case 2:

                           a_x = new byte[a.length * 8];

                           for (int i = 0; i < a.length; i++) {

                                   for (int j = 0; j < 8; j++) {

                                            a_x[i * 8 + j] = (byte) ((a[i] >>> (7 - j)) & 0x01);

                                   }

                           }

                           break;

                  case 16:

                           a_x = new byte[a.length * 2];

                           for (int i = 0; i < a.length; i++) {

                                   for (int j = 0; j < 2; j++) {

                                            a_x[i * 2 + j] = (byte) ((a[i] >>> (4 - 4*j)) & 0x0f);

                                   }

                           }

                           break;

 

                  default:

                           throw new IllegalArgumentException("suport only 216 radix");

                  }

 

                  // remove zero's

                  int pos = 0;

                  while (a_x[pos] == 0) {

                           pos++;

                  }

 

                  if (pos == 0) {

                           return a_x;

                  } else {

                           byte[] a_x_new = new byte[a_x.length - pos];

                           System.arraycopy(a_x, pos, a_x_new, 0, a_x_new.length);

                           return a_x_new;

                  }

 

         }

 

         public static void main(String[] args) {

                  new ConvertDigit();

 

         }

 

}

 


-끝-

반응형