본문 바로가기
개발 노트/기초 지식

[java] 데이터 타입의 형변환, 음수의 표현

by tokkiC 2022. 4. 18.

자동 형변환

  • 내부 데이터가 숫자로만 이루어진경우, 작은 자료형에서 큰 자료형으로 이동할때 자동으로 형변환된다

데이터 손실이 없는 한에서 두 데이터 중 큰 데이터 타입을 가진 쪽에 맞추어서 자동으로 형변환됨.

화살표 방향 순서대로만 자동 형변환 가능.

실수는 지수 표현식으로 표현되므로 long -> float 형변환 가능.

int형보다 작은 데이터타입의 연산을 진행할 경우 자동으로 int 형으로 형변환 된다고 함(추후 확인해보자)

byte(1) -> short(2), char(2) -> int(4) ->
long(8) -> float(4) -> double(8)

byte a = 10;      //  작은 자료형에서 큰 자료형으로 변환
int b = a;        //  byte 형식이지만 int 에 그냥 넣어버려도 자동으로 형변환 처리되어 에러가 안뜬다

강제 형변환

  • 내부 데이터가 숫자로만 이루어진경우, 큰 자료형에서 작은 자료형으로 자동 형변환 할 때 오류가 생긴다
    오류가 발생하지 않도록 강제적으로 형변환을 시켜줄 수 있다
int a = 128;
byte b = a;

byte b = (byte)a;

System.out.println(b);

위의 결과 b의 값으로 -128 이 나오게 된다
왜냐하면 byte 는 -128 ~ 127 까지의 값만 나타낼수 있는데
128을 나타내려고 하면 127 + 1 로 억지로 만들어 표현하게 되기 때문이다

127의 데이터 컴파일 값은 컴퓨터 내에서 2진수로 1111111 인데 여기에 1의 2진수인 1을 더 하면
데이터 컴파일 값으로 10000000 을 갖게 된다. 이는 -128 을 나타내는 값이고 -128 이 나오게 된것이다

즉 큰 자료형에서 작은 자료형으로 강제 형변환 시, 완전히 다른 값이 나올 수 있다 (= 에러가 날 수 있다)

그러니 작은 자료형으로의 강제 형변환은 사용을 자제하자


문자형에서 숫자형으로의 형변환

parse 를 사용한 방법

변환후숫자형데이터타입 새변수명 = 변환후숫자형데이터타입첫대문자명사형.parse변환후숫자형데이터타입 변환할문자열변수

String s1 = "77";                      //  문자열 데이터 타입의 변수 선언
int a = Integer.parseInt(s1);          //  문자열 데이어 타입의 변수를 숫자형 데이터 타입으로 변환

value of 를 사용한 방법

변환후숫자형데이터타입 새변수명 = 변환후숫자형첫대문자데이터타입.valueOf(변환할문자열변수)

Strint s1 = "77";                      
double b = Double.valueOf(s1);

숫자형에서 문자형으로의 형변환

value Of 를 사용한 방법

문자에서 숫자로 형변환시에도 valueOf 를 사용할 수 있다

변환후문자형데이터타입 새변수명 = 변환후문자형첫대문자데이터타입.valueOf(변환할숫자형변수)

int s1 = 77;                      
String b = String.valueOf(s1);

toString 을 사용한 방법

to char은 사용하는 예가 없다고 봐도 되니 그냥 toString 으로 표현해도 될것같다

String 새변수명 = 변환전첫대문자데이터타입명사형.toString(변환할숫자형변수)

int s1 = 77;                      
String b = Integer.toString(s1);

"" (큰따옴표) 를 사용한 방법 - 되도록 사용하지 말것, 연산처리 속도 느려짐

String 새변수명 = 변환할숫자형변수 + "" // ""내부 데이터가 있을 시 문자열끼리의 덧셈으로 처리된다

int s1 = 77;                      //  tip : 작은 따옴표 '' 로 사용 시 에러뜬다 반드시 큰따옴표로 사용할 것
String b = int s1 + "";           //  큰따옴표 "" 내부가 공백이어야 s1 의 데이터만 출력된다
                                  //  이전에 String b; 로 선언하였으면 b= = int s1 + "" 로 초기화 값만 넣어도 된다
//  String b = int s1 + "감 4";   //  이처럼 "" 내부에 띄어쓰기를 포함한 데이터가 입력될 경우 b의 값은 "77감 4" 가 된다

소수점 실수에서 정수로 변환

위의 자동 형변환이 가능하지만 소수점아래의 값은 버려진다

float 의 데이터 값 뒤에는 반드시 f 를 붙여서 float 인것을 명시해야만 에러가 뜨지 않는다

자바의 실수 기본 데이터 형이 double 이므로 f가 안붙은 소수점이 있는 실수는 double 로 기본 인식되기 때문이다

float a = 1.234f;              //  float 의 값은 뒤에 f를 붙여준다. 변수 a를 선언, 초기화 하였다
int b = (int)a;                //  b 의 값은 1 이다. 소수점 아래의 데이터값은 손실된다
float c = (float)b;            //  다시 float 타입으로 변경시 c 의 값은 1.0 이된다. 손실된 데이터값이 돌아오지 않는다

int 보다 작은 데이터 타입(byte, short, char) 값의 연산값은 int 로 표시해야한다 (자동형변환의 연장선)

아마도 int 보다 작은 데이터 타입의 경우 연산시 int 자동 형변환이 되어 계산되므로

int z = byte x + byte y 와 같은 경우 계산시 int+int 로 변환되어서 byte z 가 아닌 int z 로 변환된다

byte a = 10;
byte b = 20;

int intResult = a + b;     // byte+byte 타입은 자동으로 int+int로 변환되므로 변수의 데이터타입이 byte가 아닌 int여야함

String 타입의 문자열 중 n번째 순서의 문자를 char 로 가져오려 할때 charAt(n) 을 사용

char 새변수명 = 문자열변수명.charAt(지정할색인)

문자열의 길이 이상의 색인을 입력 시 에러가 뜬다. 반드시 색인의 숫자는 문자열 길이 미만으로 입력할 것(색인에 0도 포함이므로)

String a = "tokkic";        //  문자열 변수 a 를 선언, "tokkic" 라는 문자열을 넣어 초기화했다
char b = a.charAt(0);       //  charAt(0)를 사용하여 문자열의 0번째 문자를 새로 선언한 char b 의 값으로 대입하게 한다
System.out.println(b);      //  b 의 값은 t 이다 

String 문자열 전체를 char 문자의 배열로 변환 toCharArray()

char [] 새변수명 = 문자열변수명.toCharArray()

String a = "tokkic";               //  문자열 변수 a 를 선언, "tokkic" 라는 문자열을 넣어 초기화했다
char[] b = a.toCharArray();        //  a 를 toCharArray 메소드를 이용하여 문자의 배열로 만들어 char[] b 에 대입하였다
for (int i=0; i<b.length; i++){    //  for 문을 사용하여 b의 배열 전체를 출력하였다 
System.out.println(b[i]);

데이터 타입에서 음수의 표현

byte 타입의 경우 데이터 공간은 8bit 즉 2의 8승 = 256 을 차지한다. 하지만 양수로는 0부터 127까지만 표현가능하다
나머지 반은 음수로 -128 까지 표현해야하기 때문이다.
여기서 의문점이 생긴다

2진수로 127은 1111111 8bit 즉 8개의 데이터 공간에 표현하면 앞에 남는 곳엔 0을 넣어 다음과 같다

0 1 1 1 1 1 1 1

= 127

그렇다면 저기에 1의 2진수인 1을 더하게 되면 10000000 이 들어가게 될것이고 그 해석 값은 127+1 인 128과 같을까?

1 0 0 0 0 0 0 0

= -128

아니다. 2진법으로 10000000 은 128일텐데 128이 아닌 -128이 나온다. 왜냐하면!

byte 타입은 데이터의 반은 음수를 표기해야 하기 때문이다

2진법 표기로 컴파일링 시 맨 앞의 1bit를 음수와 양수의 기호의 구분에 사용하고

남은 7bit 를 숫자표현으로 사용하므로 2의 7승인 128까지를 표현가능한것이다.

음수로는 128을 모두 표현하지만 양수로는 0도 표현해야 하므로 127까지 표현 가능하게 된 것이다

◎ 여기서 한가지 더 나아가서! 컴퓨터는 음수 계산을 어떻게 이해할까?

컴퓨터는 음수란 개념이 없기 때문에 보수(complement)라는 개념을 사용하는데

1의 보수와 2의 보수 2가지 중 대부분 2의 보수를 사용하여 음수를 표현, 계산한다

자세한 설명은 아래의 블로그에서 자세히 설명해놓았으니 헷갈릴때 참고하자

출처: https://ndb796.tistory.com/4 [안경잡이개발자]

아래는 위 사이트의 내용 중 일부이다

보수란, '두 수의 합이 진법의 밑수(N)가 되게 하는 수'를 말합니다. 예를 들어 10진수 4의 10의 보수는 6이고, 10진수 2의 10의 보수는 8입니다. 보수는 컴퓨터에서 음의 정수를 표현하기 위해서 고안되었습니다. 컴퓨터 내부에서는 사칙연산을 할 때 덧셈을 담당하는 가산기(Adder)만 이용하기 때문에 뺄셈은 덧셈으로 형식을 변환하여 계산해야 합니다. 즉 컴퓨터 내부에서는 A - B를 계산할 때 B의 보수(-B)를 구한 다음 A + (-B)로 계산하는 것입니다.

1의 보수 : 각 자릿수의 값이 모두 1인 수에서 주어진 2진수를 빼면 1의 보수를 얻을 수 있습니다.

예시 ) 2진수 1010의 1의 보수는 0101입니다.

2의 보수 : 1의 보수에 1을 더한 값과 같습니다.​

예시 ) 2진수 1010에 대한 2의 보수를 구하려면 2진수 1010에 대한 1의 보수 0101을 구한 다음 1을 더해 0110을 얻습니다.

댓글