Java

[자바의 정석] #CH.2 변수 Variable - 2.4 기본형(primitive type)

소댓 2023. 1. 18. 09:56

4. 기본형(primitive type)

 

4.1 논리형 - boolean

- boolean형 변수 : true와 false 중 하나를 저장할 수 있으며 기본값(default)은 false

- boolean형 변수는 대답(yes/no), 스위치(on/off) 등의 논리구현에 주로 사용

- 1bit 만으로도 충분하지만 자바에서는 데이터를 다루는 최소단위가 byte이기 때문에 boolean의 크기가 1byte

1
2
boolean power = true; // power라는 boolean형 변수를 선언하고 true로 변수 초기화
boolean checked = False; //에러. 대소문자가 구분됨. true 또는 false만 
cs

> 자바에서는 대소문자가 구별되기 때문에 TRUE와 true는 다른 것으로 구별됨!

 

 

4.2 문자형 - char

- 문자를 저장하기 위한 변수를 선언할 때 사용됨

- char 타입의 변수는 단 하나의 문자만을 저장할 수 있음

1
char ch = 'A'; // 문자 'A'를 char타입의 변수 ch에 저장.
cs

> 변수에 '문자'가 저장되는 것 같지만, 사실은 문자가 아닌 '문자의 유니코드(정수)'가 저장되는 것 : 변수 ch에는 65가 저장됨

- 문자 리터럴 대신 문자의 유니코드를 직접 저장하기 위해서는,

1
2
char ch = 'A'; // 문자 'A'를 char타입의 변수 ch에 저장
char ch = 65; // 문자의 코드를 직접 변수 ch에 저장
cs

- 만일 어떤 문자의 유니코드를 알고 싶으면, char형 변수에 저장된 값을 정수형(int)으로 변환하면 됨 > 형변환

1
int code = (int)ch; // ch에 저장된 값을 int타입으로 변환하여 저장한다.
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
public class CharToCode_ {
 
    public static void main(String[] args) {
        char ch = 'A'// char ch = 65;
        int code = (int)ch; // ch에 저장된 값을 int타입으로 변환하여 저장한다.
        
        System.out.printf("%c=%d(%#X)%n", ch, code, code); 
        // 'A'의 유니코드 65(16진수로 0x41)
        
        char hch = '가'// char hch = 0xAC00;
        System.out.printf("%c=%d(%#X)%n", hch, (int)hch, (int)hch); 
        // 문자 '가'의 유니코드는ㄴ 44032(16진수로 0xAC00)
    }
 
}
 
cs
더보기

A=65(0X41)
가=44032(0XAC00)

 

* 특수 문자 다루기

- 영문자 이외에 tab이나 backspace 등의 특수문자를 저장하는 방법

1
char tab = '\t'; // 변수 tab에 탭 문자를 저장 
cs
  • tab = \t
  • backspace = \b
  • form feed = \f
  • new line = \n
  • carriage return = \r
  • 역슬래쉬(₩) = \\
  • 작은따옴표 = \'
  • 큰따옴표 = \"
  • 유니코드(16진수)문자 = \u유니코드 (예: char a='\u0041'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
public class SpecialCharEx_ {
 
    public static void main(String[] args) {
        System.out.println('\''); // '''처럼 할 수 없다.
        System.out.println("abc\t123\b456"); // \b에 의해 t123이 지워진다.
        System.out.println('\n'); // 개행(new line)문자 출력하고 개행
        System.out.println("\"Hello\""); // 큰따옴표를 출력하려면 이렇게 한다.
        System.out.println("c:\\"); 
 
    }
 
}
 
cs

 

* char타입의 표현형식

- char타입의 크기는 2byte(=16bit)임

- 1비트로 표현할 수 있는 정수의 개수 : 2^16개(65536개)

> short타입의 표현범위 : -2^15 ~ 2^15-1 (-32768~32767)

> char타입의 표현범위 : 0 ~ 2^16-1 (0~65536)

1
2
3
4
5
6
char ch = 'A'; // har ch = 65;
short s = 65;
 
System.out.println(ch); // A가 출력
System.out.println(s); // 65가 
 
cs

> println()은 변수 타입이 정수형이면 변수에 저장된 값을 10진수로 해석하여 출력하고, 

   문자형이면 저장된 숫자에 해당하는 유니코드 문자를 출력함 

> 따라서, 값의 타입까지 알아야 올바르게 해석할 수 있음

 

* 인코딩과 디코딩

- 문자 인코딩(encoding) : 문자를 코드로 변환하는 것

- 문자 디코딩(decoding) : 코드를 문자로 변환하는 것

> 문자를 저장할 때는 인코딩을 해서 숫자로 변환해서 저장,

   저장된 문자를 읽어올 때는 디코딩으로 숫자를 원래의 문자로 되돌림

 

* 아스키(ASCII)
- ASCII : 정보교환을 위한 미국 표준 코드

- 128개의 문자 집합을 제공하는 7bit 부호로 숫자 '0~9', 영문자 'A~Z'와 'a~z'가 연속적으로 배치됨 > 프로그래밍에서 활용

 

* 확장 아스키(ASCII)와 한글

- 확장 아스키 : 아스키의 남는 1bit를 활용하여 문자를 추가로 정의한 것 

- 한글 윈도우에서 작성된 문서는 확장 완성형(CP 949)를 기본으로 사용하여 인코딩되어 저장됨

 

* 코드 페이지(code page, cp)

- 확장 아스키의 256개 문자를 어떤 숫자로 변환할 것인지를 적어놓은 '문자 코드표'

 

* 유니코드(Unicode)

- 전 세계의 모든 문자를 하나의 통일된 문자집합으로 표현한 것

- 모든 문자의 크기가 동일한 UTF-16이 문자를 다루기는 편리하지만 문서의 크기가 커지기 때문에,

  UTF-8인코딩으로 작성된 웹문서의 수가 빠르게 늘고 있다. 

 

 

4.3 정수형 - byte, short, int, long

- byte(1byte) < short(2byte) < int(4bye) < long(8byte)

 

* 정수형의 표현형식과 범위  

- n비트로 표현할 수 있는 정수의 개수 : 2^n개(=2^n-1개 + 2^n-1개)

- n비트로 표현할 수 있는 부호있는 정수의 범위 : -2^n-1 ~ 2^n-1 -1

> 8비트로 표현할 수 있는 정수의 개수 : 2^8개(=2^7개 + 2^7개)

> 8비트로 표현할 수 있는 부호있는 정수의 범위 : -2^7 ~ 2^7 -1(-128~127)

종류/크기 1byte(=8bit) 2byte(=16bit) 4byte(=32bit) 8byte(=64bit)
정수형 byte
(-128~127)
short
(O:-32768~32767)
(X:0~65535)
int
(-20억~20억)
long
(-800경~800경)

 

* 정수형의 선택기준

>> 정수형 변수를 선언할 때는 int타입으로, int의 범위(약 +-20억)를 넘어서는 수를 다룰 때는 long을 사용

 

* 정수형의 오버플로우

- 오버플로우(overflow): 해당 타입이 표현할 수 있는 값의 범위를 넘어서는 것

> 에러가 발생하진 않지만, 예상치 못한 결과를 얻게 됨으로 애초에 충분한 크기의 타입을 선택해서 사용해야 함

- 마치 계수기를 거꾸로 돌리는 것처럼, '0000'에서 정방향으로 돌리면 '0001'이 되지만 역방향으로 돌리면 '9999'가 됨

- 정수형 타입이 표현할 수 있는 최대값에 1을 더하면 최소값이 되고, 최소값에서 11을 빼면 최대값이 됨

> 최대값 +1 → 최소값

> 최소값 -1 → 최대값

 

* 부호있는 정수의 오버플로우

- 부호없는 정수와 부호있는 정수는 최대값과 최소값이 다르기 때문에 오버플로우가 발생하는 시점이 다름

> 부호없는 정수는 2진수로 '0000'이 될 때 오버플로우가 발생하고,

> 부호있는 정수는 부호비트가 0에서 1이 될 때 오버플로우가 발생함

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
public class OverflowEx {
 
    public static void main(String[] args) {
        short sMin = -32768// sMin : 최소값
        short sMax = 32767// sMax : 최대값
        char cMin = 0;
        char cMax = 65535;
        
        System.out.println("sMin= " + sMin);
        System.out.println("sMin-1= " + (short)(sMin-1)); // 최소값-1 = 최대값
        System.out.println("Max= " + sMax);
        System.out.println("Max+1= " + (short)(sMax+1)); // 최대값+1 = 최소값
        System.out.println("cMin= " + (int)cMin);
        System.out.println("cMin+1= " + (int)--cMin); // 최소값-1 = 최대값
        System.out.println("Max= " + (int)cMax);
        System.out.println("Max+1= " + (int)++cMax); // 최대값+1 = 최소값
 
    }
 
}
 
cs
더보기

sMin= -32768
sMin-1= 32767
Max= 32767
Max+1= -32768
cMin= 0
cMin+1= 65535
Max= 65535
Max+1= 0

> short smax의 Max를 MAX로 입력해서 아래에 Max들이 다 오류로 뜨는 거였음..

 

 

4.4 실수형 - float, double

 

*실수형의 범위와 정밀도

- float(32bit, 4byte) : 1.4x10^-45 ~ 3.4x10^38 > 정밀도 7자리

- double(64bit, 8byte) : 4.9x10^-324 ~ 1.8x10^308 > 정밀도 15자리

> 얼마나 0에 가깝게 표현할 수 있는가가 중요

 

Q. 실수형도 정수형처럼 오버플로우가 발생할까?

- 실수형에서는 오버플로우가 발생하면 변수의 값은 '무한대'가 됨

- 정수형에는 없는 '언더플로우'가 존재하는데, 실수형으로 표현할 수 없는 최소값보다 작은 값임 > 변수의 값은 0이 됨

 

- 실수형에서는 표현할 수 있는 값의 범위 뿐만 아니라 '정밀도(precision)'도 중요함

> 정수형과 달리 실수형은 오차가 발생할 수 있기 때문

- 실수형 값을 저장할 때,  '보다 높은 정밀도'를 위해 float타입이 아닌 double타입의 변수를 사용

> 7자리 이상의 정밀도가 필요하다면, 변수의 타입을 double로 해야 함

> float은 연산속도의 향상이나 메모리 절약을 위해 선택

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
public class FloatEx1_ {
 
    public static void main(String[] args) {
        float f = 9.12345678901234567890f;
        float f2 = 1.2345678901234567890f;
        double d = 9.12345678901234567890d;
        
        System.out.printf("     123456789012345678901234%n");
        System.out.printf("f : %f%n", f); // %f : 실수형 값 출력, 소수점 이하 6째자리까지 출력
        System.out.printf("f : %24.20f%n", f); // %24.20f : 전체 24자리 중 20자리는 소수점 이하의 수 출력
        System.out.printf("f2 : %24.20f%n", f2);
        System.out.printf("d : %24.20f%n", d);
        
    }
 
}
cs
더보기

     123456789012345678901234
f : 9.123457
f :   9.12345695495605500000
f2 :   1.23456788063049320000
d :   9.12345678901234600000

 

* 실수형의 저장형식

- 실수형은 값을 부동소수점수(floating-point)의 형태로 저장함

- 부동소수점수 : 부호(Sign), 지수(Exponent), 가수(Mantissa) > 세 부분으로 이루어짐

 

- 실수 표현형식의 구성요소

① S - 부호(Sign bit) : 0이면 양수, 1이면 음수

② E - 지수(Exponent) : 부호있는 정수. 지수의 범위는 -127~128(float), -1023~1024(double)

③ M - 가수(Mantissa) : 실제값을 저장하는 부분. 10진수로 7자리(float), 15자리(double)의 정밀도로 저장 가능

 

* 부동소수점의 오차

- 2진수로 변환된 실수를 저장할 때, 정규화 과정을 통해 1.XXX x 2^n 형태로 변환함

> 정규화된 2진 실수는 항상 '1.'으로 시작하기 때문에, '1.'을 제외한 23자리의 2진수가 가수로 저장되고 그 이후는 잘림

> 이 때 잘려나간 값들에 의해 발생할 수 있는 최대 오차는 가수의 마지막 비트의 단위와 같음

1
2
3
4
5
6
7
8
9
10
11
12
13
 
public class FloatToBinEx {
 
    public static void main(String[] args) {
        float f = 9.1234567f;
        int i = Float.floatToIntBits(f);
        
        System.out.printf("%f%n", f);
        System.out.printf("%X%n", i); // 16진수로 출력
    }        //main의 끝
 
}
 
cs

 

더보기

9.123457
4111F9AE // 4111F9AD의 2진수 마지막 자리 두 자리의 값이 '01'에서 '10'으로 1증가