ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2. 자바 변수와 자료형 (3) byte, short, int, long
    자바(Java) 강의 2019. 3. 4. 11:58

     

    이 포스트에서는 자바 프로그래밍 언어의 기본 자료형인 char, boolean, byte, short, int, long, float, double중에서 숫자를 표현 할 수 있는 byte, short, int, long에 대해 알아보도록 하겠다. 

    예상 독자

    목표

    • 정수를 표현하기 위한 자료형
    • 자료형의 크기에 따른 비교
    • byte
    • short
    • int
    • long
    • [더 알아보기] 자료형(Data Type)의 의미

    정수를 표현하기 위한 자료형

    byte, short, int, long은 모두 정수를 표현하기 위한 자료형이다. 표현하고자 하는 자료(data)가 같으므로 한 포스트에서 같이 정리하고 비교하는것이 이해하기 더 효율적이라 판단해 한 포스트에서 다루게 되었다. 다시 말하지만 byte, short, int, long은 모두 정수를 표현하기 위한 자료형이다. 그렇다면 왜 한 자료(data)를 표현하는데 이렇게 많은 자료형이 필요할까? 바로 메모리 제약 때문이다. 각 자료형은 정수를 표현하지만 그 정수를 표현 할 수 있는 범위가 존재한다. 이 범위는 해당 자료형에 할당된 메모리 크기에 비례한다. 우리 소프트웨어 엔지니어들은 우리가 개발하는 소프트웨어가 어떤 데이터를 필요로하고 이 데이터가 어떤 범위내에 존재하는지 파악하여 이를 표현하기 위한 가장 적합한 자료형을 찾아야한다. 가장 메모리 활용성이 좋은 자료형을 찾는게 좋다. 그럼 이제 정수형 자료형들의 크기에 대해 알아보자.

    자료형의 크기에 따른 비교

     

    [자료형의 크기 (long 은 8 bytes입니다. 그림 오류)]

    자료형을 크기에 따라 비교하면 위와 같다. 네모 하나를 1 byte (8 bits)로 봤을 때 2의 제곱수로 그 크기가 커지는 것을 확인 할 수 있다. 이 비트가 무슨 의미이냐하면 여러분이 어떤 자료(여기선 정수)를 선언하면 그 자료형의 크기에 해당하는 공간이 메모리에 할당된다는 의미이다. 예를들어 여러분이 byte형의 어떤 정수를 선언하면 메모리에 8비트만큼의 공간이 해당 정수를 위해 할당된다는 뜻이다. 

    그렇다면 각 비트에는 몇개의 수를 저장 할 수 있을까? 

    1 bit부터 생각 해 보자. 1 비트에는 2개의 숫자를 저장 할 수 있다. 0과 1.  2 비트에는 몇개의 수를 저장 할 수 있을까? 00, 01, 10, 11 이렇게 네개의 수를 저장 할 수 있다. 3비트에는 몇개의 수를 저장 할 수 있는가? 000, 001, 010, 011, 100, 101, 110, 111이렇게 8개의 수를 저장 할 수 있다. 그렇다면 n비트에는 몇개의 수를 저장 할 수 있는가? 2^n개의 수를 저장 할 수 있다. 16비트에는 몇 개의 수를 저장 할 수 있는지 계산 해 보자. (계산기를 이용해도 좋다.) 답은 65,536개이다.

    byte

    byte형은 정수 자료형 중에서도 가장 작은 범위를 가진 자료형이다. byte에는 8비트의 공간이 할당되며 256개의 숫자를 저장 할 수 있다. 이 256개의 숫자는 반으로 나뉘어 반은 음수를 나머지 반은 양수와 0을 표현한다. 256을 2로 나누면 몇인가? 바로 128이다. 따라서 byte형은 128개의 음수와 0 그리고 127개의 양수를 표현한다. 표현 범위는 -128~127이다.
    public class Main {
    	public static void main(String[] args) {
    		byte val = 10;
    		System.out.println(val);
    	}
    } 
    
    //실행 결과: 10
    음수가 표현되는지 확인 해 보자.
    public class Main {
        public static void main(String[] args) {
            byte val = -10;
            System.out.println(val);
        }
    }  
    
    // 실행 결과: -10
    이번엔 최솟값을 넣어보자.
    public class Main {
      public static void main(String[] args) {
        byte val = -128;
        System.out.println(val);
      }
    } 
    //실행 결과: -128

     

    이번엔 최솟값보다 하나 더 작은 값을 넣어보자.
    public class Main {
      public static void main(String[] args) {
        byte  val  = -129;
        System.out.println(val);
      }
    }
    
    //실행 결과: Error:(3, 20) java: incompatible types: possible lossy conversion from int to byte​
    에러가 나는 것을 확인 할 수 있다. 무슨 뜻인가? incompatible types: 호환되지 않는 자료형이라는 뜻이다. 또 int(-129)를 byte로 변경하려고 했기 때문에 이 에러가 났음을 암시한다. 이제 byte의 최댓값도 시도 해 보자.
    public class Main {
      public static void main(String[] args) {
        byte val = 127;
        System.out.println(val);
      }
    } 
    
    //실행 결과: 127​
    이제 128을 넣고 실행 해 보자.
    public class Main {
      public static void main(String[] args) {
        byte val = 128;
        System.out.println(val);
      }
    
    } 
    
    //실행 결과: Error:(3, 20) java: incompatible types: possible lossy conversion from int to byte
    마찬가지로 같은 결과가 나오는 것을 확인 할 수 있다. 그렇다면 byte가 몇 비트인지 어떻게 확인 할까? 바로 Byte.SIZE로 확인 할 수 있다. 이 포스트에서 내가 거짓말을 하고 있는지 아닌지 확인 하기 위해 Byte.SIZE를 출력 해 보자.
    public class Main {
      public static void main(String[] args) {
        System.out.println(Byte.SIZE);
      }
    } 
    
    //실행 결과: 8

    8 (bits)를 출력하는 것을 확인 할 수 있다.

    short

    short는 byte다음으로 작은 자료형이다. short는 2바이트의 크기 즉 16 bits를 저장 할 수 있다. 16 bits에는 65,536개의 숫자를 저장 할 수 있다. 마찬가지로 이 자료형도 65,536을 둘로 나눠 32,768개의 음수와 32,768개의 0과 양수를 표현한다. 따라서 -32,768~32,767까지의 정수를 표현 할 수 있다.
    public class Main {
      public static void main(String[] args) {
        short val = 200;
        System.out.println(val);
      }	
    } 
    
    //실행 결과: 200
    200으로 예제를 만든 이유는 127까지 표현 가능한 byte와 구분하기 위해서이다. 이제 음수는 본인이 실습 해 보도록 하자.
    public class Main {
        public static void main(String[] args) {
            short val = 32768;
            System.out.println(val);
        }
    }  
    // 실행 결과: Error:(3, 21) java: incompatible types: possible lossy conversion from int to short
    32,767보다 큰 수를 넣으면 위처럼 자료형이 같지 않아 컴파일 에러가나는 것을 확인 할 수 있다. 마찬가지로 -32,768보다 작은 음수를 넣어 에러가 나는 것을 확인 해 봐라.
    byte에서 했던 것과 마찬가지로 short의 크기를 확인 해 보자.
    public class Main {
      public static void main(String[] args) {
        System.out.println(Short.SIZE);
      }
    } 
    
    //실행 결과: 16
    말한대로 16 (bits)를 출력하는 것을 확인 할 수 있다.

    int

    int는 integer(정수)의 약자이고 4 bytes(32 bits)의 크기를 가진 자료형으로 가장 보편적으로 쓰이는 정수형이기도 하다. 32 bits에는 4,294,967,296개의 숫자를 저장 할 수 있다. 이 숫자는 별로 중요하지 않다. 이 숫자를 외우려고 하지 말아라. 2^32개를 저장 할 수 있다는 것만 이해하면 된다. 마찬가지로 반으로 나눠 반은 음수를 나머지 반은 0과 양수를 표현한다. 표현 할 수 있는 숫자의 범위는  -2,147,483,648 ~ 2,147,483,647이다.
    public class Main {
      public static void main(String[] args) {
        int val = 32768;
        System.out.println(val);
      }
    } 
    
    // 실행 결과: 32768
    이제 최댓값보다 1보다 큰 수를 넣어보자.
    public class Main {
      public static void main(String[] args) {
        int val = 2147483648;
        System.out.println(val);
      }
    } 
    
    //실행 결과: Error:(3, 19) java: integer number too large: 2147483648​
    실행을 하면 위처럼 에러가 나는 것을 확인 할 수 있다.
    public class Main {
      public static void main(String[] args) {
        int val = -2147483649;
        System.out.println(val);
      }
     } 
    
    // 실행 결과: Error:(3, 20) java: integer number too large: -2147483649​
    마찬가지로 최솟값을 넘는 경우 에러가 나는 것을 확인 할 수 있다. 
    public class Main {
      public static void main(String[] args) {
        System.out.println(Integer.SIZE);
      }
    } 
    
    //실행 결과: 32
    정수형의 크기로 32 bits을 리턴 하는 것을 확인 할 수 있다.

    long

    long 형을 사용하면 int보다 더 큰 수를 할당 할 수 있다. long의 크기는 8 bytes (64 bits)이다. 숫자가 너무 크니 계산은 생략하겠다. 
    public class Main {
      public static void main(String[] args) {
        long val = 30;
        System.out.println(val);
      }
    } 
    
    //실행 결과: 30
    그렇다면 정말로 int의 범위보다 큰 수를 할당 할 수 있을까? 있다. 그러나 룰이 있다. int의 범위보다 큰 수를 할당해야 할 때는 숫자의 마지막에 L을 붙여야 한다는 점이다. 그렇지 않으면 컴파일러가 int로 인식하고 에러를 낸다.  
    public class Main {
      public static void main(String[] args) {
        long val = 2147483648L;
        System.out.println(val);
      }
    } 
    
    // 실행 결과: 2147483648
    위처럼 int보다 큰 값에는 L를 붙여야 함을 확인 할 수 있다. 마찬가지로 크기를 확인 해 보자.
    public class Main {
      public static void main(String[] args) {
        System.out.println(Long.SIZE);
      }
    } 
    
    //실행 결과: 64
    64 비트를 출력하는 것을 확인 할 수 있다.

    [더 알아보기] 자료형(Data Type)의 의미

    이 섹션은 현 단계에서 반드시 알아야하는 개념은 아니다. 이후에 다시 설명 할 기회가 있을것이다. 하지만 '형'이라는게 무슨 의미인지 궁금하다면 읽어보는 것을 추천한다. 아래와 같은 예제를 보자.
    public class Main {
      public static void main(String[] args) {
        short val = 'c';
        System.out.println(val);
      }
    } 
    
    //실행 결과: 99
    이게 대체 무슨일인가? 어떻게 short형으로 선언된 val에 char형인 'c'가 들어갔으며, 결과 값은 어떻게 99가 나온것인가? 도대체 변수 앞에 붙은 int, short, byte, char의 의미는 무엇인가?
    처음 자바 변수와 자료형 ( 2. 자바 변수와 자료형  (1) char ) 에서 자료형에 대해 설명했을 때, 이렇게 말했다;'또 각 자료가 표현 할 수 있는 범위는 해당 자료형의 표현 방식과, 메모리 공간의 제약에 의해 결정된다.' 우리는 지금까지 메모리 제약에 대해 알아보았다. byte는 사이즈가 어떻고, int는 사이즈가 어떻고, ...그리고 표현 방식은 어떻게 설명했는가? char는 문자하나를 표현하고, boolean은 참 거짓을 표현하고, byte, short, int, long은 정수를 표현한다고 했다. 이런 표현 방식이란 누구를 위한 개념인가? 바로 우리 인간을 위한 개념이다. 컴퓨터의 입장에서는 char이든 short이든 상관 없이 1과 0으로 표현된다. 따라서 컴퓨터는 메모리에 할당 된 해당 자료가 무슨 형인지 알지 못한다. 아래의 그림을 기억하는가?

    c값을 할당하면 메모리에 뭐가 들어가는가? 0000000001000011이 메모리로 들어간다. 이제 아래를 보자.

     

    이해를 돕기 위해 char와 크기가 같은 short val에 99를 할당했다. 그러면 메모리에는 무슨 값이 들어가는가? 0000000001000011이 들어간다. 이 값은 무슨 값이랑 같은가? 그렇다 'c'를 넣었던 값과 같은 값이다! 컴퓨터는 메모리에 할당된 자료가 무슨 형인지 알지 못한다는 뜻은 바로 이런 뜻이다. 우리가 'c'를 저장하든 99를 저장하든 메모리에는 0000000001000011가 들어간다. 따라서 short val = 'c'를 넣어도 0000000001000011의 값이 들어가므로 short var입장에서는 범위를 넘지 않으니 그냥 받아들이는 것이다. 그렇다면 이런 '형'이란 어느 레벨에서 관리되는가? 바로 컴파일러/운영체제(모니터 디바이스 드라이버) 레벨에서 관리된다. (그냥 그렇구나 하고 넘어가도 된다.) 어떤 자료형이든 하드웨어 레벨에서는 결국 1과 0일뿐임을 기억하고 넘어가면 된다.

    public class Main {
      public static void main(String[] args) {
        short val = 'c';
        System.out.println(val); // 이 값은 short 즉 정수로 해석 해야 하는구나!
      }
    } 
    
    //실행 결과: 99

    'c'를 집어 넣었지만 변수의 타입이 short이므로 System.out.println이라는 모니터에 값을 출력하는 기능을 가진 녀석이 "아, 이 값은 short로 선언되어 있으니 지금 메모리에 할당된 0000000001000011을 short타입의 정수형으로 해석해 출력 해야겠구나."라고 이해한다는 뜻이다.

    형에 대해서는 이후 형 변환을 설명하며 더 자세히 이야기 할 예정이니 그 때가서 더 이해해도 좋다.

     이번 포스팅에서는 자바에서 정수형을 표현하기 위한 자료형들을 알아보았다. 그리고 마지막에 자료형의 의미가 무엇인지에 대해 다시 한번 생각 해 보았다. 여러분에게 질문이 있다. 위에서 정수형에 대해 설명 할 때, 예를들어 byte 라면 8비트는 2^8=256개의 숫자를 표현 할 수 있고 256개 중 반은 음수로 나머지 반은 0과 양수로 사용한다고 했다. 그렇다면 8비트로 음수를 어떻게 표현해야 할까? 여러분이 컴퓨터를 만드는 사람이라면 2진수로 음수를 어떻게 표현 할 것인가? 사칙연산이 용이하도록 설계 할 수 있는가? 이런 논의는 다음 포스트에서 설명할 float과 double에서도 계속된다. float과 double은 소수점을 표현하기 위한 자료형이다. 2진수로 소수점을 어떻게 표현 할 것인가? 다음 포스트로 들어가기전에 한번 생각 해 보기 바란다. 이 질문에는 정답이 없다. 여러분은 앞으로 개발을 하면서 자료를 정의하는데 많은 시간을 투자 할 것이다. 어떻게 자료를 정의해야 더 효율적으로 구현 가능한지에 대해 고민하게 될 것이다. 이 질문은 그런 상황의 일환이다. 아무리 비효율적인 것 같아도 스스로 데이터의 표현방식을 정의했다는건 고무적인 일이다. 따라서 주저하지 말고 고민 해 보길 바란다. 

     

    다음 포스트: 2. 자바 변수와 자료형 (4) float, double

     

    댓글

f.software engineer @ All Right Reserved