언어/[Java]

[Java] 비트 연산자, 타입변환, 문자(char)타입

dayeonsheep 2023. 7. 25. 16:27

0. 비트 연산자


비트와 바이트

  • bit = 컴퓨터가 처리하는 정보의 최소 단위 / 한 개만 저장 불가능(데이터 나타내기에 턱없이 부족) / 8개 비트 묶은 byte 사용
  • 1byte는 0000000 부터 11111111까지 값 표현 가능
  • 1byte를 정수로 표현하면 0~254까지 표현 가능(부호 비트가 없다고 가정)
  • 1byte를 16진수로 표현하면 00~FF까지 표현 가능(4비트는 0~15까지 표현가능하기 때문)

 

비트 연산자 (비트 단위로 논리 연산을 할 때 사용하는 연산자)

  • 정수형 타입을 비트로 표현했을 때, 맨 좌측 비트 = 부호화비트 / 1이면 음수, 0이면 양수
  • << : 명시된 수만큼 비트들을 전부 왼쪽으로 이동시킴
    • 좌측으로 n 쉬프트 연산 = 2^n 로 곱하기
  • >> : 부호를 유지하면서 지정한 수만큼 비트를 전부 오른쪽으로 이동시킴
    • 우측으로 n 쉬프트 연산을 하라는 것 = 2^n 으로 나눈 결과값이 됨
  • >>> : 지정한 수만큼 비트 전부 오른쪽 이동, 새로운 비트는 전부 0이 됨
    • >>> 결과 = 무조건 양수
    • 10000000 >>> 2 를 하게 되면 00100000 이 됨
int a = 4;
int b = a>>1; //2^1 으로 나눈다
System.out.println(b); // 2출력

int c = 4;
int d = c<<1; //2^1 으로 곱한다
System.out.println(d); // 8출력

 

 

 

1. 타입 변환


double형 타입 -> 정수값 잘 대입됨

  • 묵시적 타입 변환(자동 타입 변환, implicit conversion)이라고 함.
double d1 = 50; //int형 리터럴 50
double d2 = 500L; //long형 리터럴 500L

 

int형 타입 -> 실수 대입하면 오류 발생

int i1 = 50.0;
int i2 = 25.4f; //컴파일 에러
int i2 = (int)50.0 //명시적 타입 변환
  • 정수는 실수 포함X -> 컴파일 오류
  • 실수 값을 정수 타입 변수에 저장하려면 정수타입으로 형변환, 앞에 (int) 붙이기
  • 소수점 이하 부분 잘림
  • 명시적 타입 변환(강제 타입 변환, explicit conversion)이라고 함

 

크기가 큰 타입은 작은 타입 저장 가능

long-8 / int-4 / short-2 / byte-1

- 기본 자료형 중 boolean을 제외하면 모든 자료형은 형변환이 가능

long x3 = Long.MAX_VALUE; //long이 표현할 수 있는 최댓값 x3에 넣기
int i3 = (int)x3; 
System.out.println(x3);
System.out.println(i3); //-1 출력됨

long->4byte씩 2칸(양수일 때는 맨 좌측 2진수=0)

01111111 11111111 11111111 11111111  11111111 11111111 11111111 11111111 

long이 가진 가장 큰 값을 int형 타입 변수에 저장하게 되면 뒷부분 4byte가 저장
-> 다 1로 채워진 값 가지게 됨

-> 가장 좌측 비트 1일 경우 음수 (모두 다 1로 채워져있으면 음수 1 , -1이 됨)

 

강제 형변환시 주의점

강제적인 동작이므로 만일 데이터의 손실이 일어난다면 정확한 연산을 수행할 수 없기 때문에 예상하지 못한 결과를 얻을 수 있다는 것

byte b = 100; 
byte b = (byte)100; // byte의 범위는 -128 ~ 127이기 때문에 데이터 손실 없이 대입이 가능하고 컴파일러가 자동 형변환을 해준다.

---------------------------------------

int i = 100;
byte b = i; // 에러, 변수이기 때문에 상수일 때랑 다르다. 컴파일러는 변수 안에 값을 알지 못하기 때문에
byte b = (byte)i;

---------------------------------------

byte b = 1000; // 에러, byte 타입의 범위를 넘었기 때문에 자동 형변환 x
byte b = (byte)1000; // b에 -24가 대입된다.

 

float과 int 형변환 주의점

정수 타입을 실수 타입으로 변환할 때 정밀도 손실을 피해야 함

/* int 값을 float 타입으로 자동 변환하면서 문제가 발생한 예*/
int num1 = 123456780;
int num2 = 123456780;

float num3 = num2; //num2를 float 타입으로 변환
System.out.println(num3); // 1.23456784 * E8

num2 = (int)num3; //다시 int 타입으로 변환해서 num2에 저장
System.out.println(num2); // 123456784

int result = num1 - num2; //num1에서 num2를 뺀 결과를 변수 result에 저장
System.out.println(result); // -4

 

 

- float타입 비트 수 할당

출처: https://inpa.tistory.com/entry/JAVA-☕-타입-형변환-종류-방법-💯-총정리#

가수 23bit 가 최대로 표현할 수 있는 값 = 16,777,215

따라서 123,456,780은 23비트로 표현할 수 없어서 근사치로 변환됨

=>정밀도 손실!

 

이를 방지하기 위한 해결책->가수부가 더 크게 할당되어있는 double타입 사용하기

double타입 비트 수 할당

 

형변환 안전장치

코드에서 데이터 값을 검사하기 위한 기본 타입에 대해 최대값/최소값을 상수로 제공하고 있음

(boolean , char 타입 제외)

이걸 활용해서 최소, 최대값 벗어나는지 아래와 같이 검사해 볼 수 있음

int i = 128;

if( (i < Byte.MIN_VALUE) || (i > Byte.MAX_VALUE) ) {
	System.out.println("byte 타입으로 변환 할 수 없음"); // 실행 (byte의 최대 크기는 127)
} else {
	byte b = (byte) i;
    System.out.println(b); 
}

 

2. 문자타입


  • 문자열(String)-큰 따옴표, ex. "a"
  • 문자(char)-작은 따옴표, 2byte, 유니코드 값을 가짐(0000~0FFF, 이건 2바이트를 16진수로 표현한 것)
    • 10진수(0~9까지의 수로 표현), 16진수(0~15까지의 수로 표현)
    • 1byte를 반으로 쪼갠 거(=4bit)로 표현할 수 있는 게 16진수 / 1byte로 표현할 수 있는 16진수 = 00~FF까지

 

문자타입은 0~65535까지 저장할 수 있는 정수타입이기도 함

  • short는 2byte 정수타입인데 음수, 0, 양수를 표현
  • char는 2byte 정수 타입이 될 수 있는데 0과 양수만 표현 -> 그래서 short보다 양수는 더 많은 수를 표현할 수 있음. char는 bit로 표현할 때 맨 왼쪽에 있는 비트를 부호비트로 사용하지 않기 때문
char c1 = 'a';
System.out.println((int)c1); // a가 유니코드 몇 번째 위치하고 있는지 숫자가 출력, 97출력됨

char c2 = (char)97; // 유니코드 97번째 문자를 c2에 저장하라는 의미
System.out.println(c2); // a 출력됨

 

응용 - 'a'부터 'z'까지 출력

char c3 = 'a';

while(c3 <= 'z'){
    System.out.println(c3);
    c3++;
}

 

 


<참고 및 출처>