Post List

2018/01/16

C#__6.0 데이터간 형변환

데이터 형변환에 대해서도 알아보겠습니다. 이전 살펴본 박싱과 언박싱도 형식과 참조 형식간의 형식 변환이라고 있습니다. 5가지 형변환에 대해 알아보겠습니다.

첫번쨰로, 크기가 서로 다른 정수 형식 사이의 변환입니다. 작은 정수형 변수에 있는 데이터를 정수형 변수로 옮길 때는 문제가 없지만,
반대의 경우, 정수형 변수에 있는 데이터가 작은 정수형 변수의 크기보다 경우 형변환이 일어나게되면 오버플로우가 발생합니다. , 정수형 변수에 담긴 데이터크기가 작은 정수형 변수가 수용할 있는 크기보다 작을 경우에는 문제가 없지요.

코드로 한번 확인해보겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
sbyte a = 127;
 
int b = (int)a;
 
// 문제가 없음
 
 
 
int x = 128;
 
sbyte y = (sbyte)x;
 
// 오버플로우 발생
 
 
 
 
cs


1
2
3
4
5
6
int x = 20;
 
 
sbyte y = (sbyte)x;
 
// 문제 없음.
cs

두번째는 크기가 서로 다른 부동 소수점 형식 사이의 변환입니다. Float double사이의 형변환의 경우에 해당하겠는데요, 정수형 형변환에서 발생했던 오버플로우는 아니지만, float double 소수점을 몇자리까지 수용하냐의 차이가 있습니다. 그리고 소수를 이진수로 메모리에 보관하지요. 이것을 다른 형식으로 (float에서 double, 혹은 double에서 float)변환하려면 10진수로 복원한 , 다시 이진수로 변환해서 기록하게 됩니다. 문제는 이진수로 표현하는 소수가 완전하지 않다는데에 있습니다.
1/3같은 수는 0.33333…….. 무한 소수가 됩니다. 따라서 정밀한 수를 다뤄야 하는 프로그램에서 float double사이의 형식 변환을 시도할 때는 주의를 기울여야 합니다.

1
2
3
float  a = 12.345f;
 
double b = (double)a;
cs
  


세번째는 부호 있는 정수 형식과 부호 없는 정수 형식 사이의 변환입니다. 여기서 부호란 (-) (+) 의미합니다. 1바이트 데이터타입을 예로 들었을 sbyte -128~127 값을 담을 있고 byte 0 ~ 255까지 담을 있습니다. 담을 있는 수가 다를까요, 똑같이 1바이트를 사용하는데 말이죠?! 2^8 = 256 256가지의 수를 표현할 있는데 말입니다. 이유는 byte 8개의 비트를 모두 수를 표현하는데 사용되는 반면, sbyte 1개의 비트는 부호를 표현하는데 사용됩니다. 이것을 부호비트(Sign bit)라고 하지요. 그래서 나머지 7개의 비트로 수를 표현하는데 사용됩니다.
0 1 1 1 1 1 1 1  127입니다. 그럼
1 1 1 1 1 1 1 1 몇일까요? 부호비트가 1이기때문에 당연히 -127 생각하기 쉽지만 -1이랍니다. 이런경우 부호 비트는 순수하게 음과 양을 나타내고 나머지 비트도 순수하게 수를 나타내는데에만 사용된다면 -127 맞습니다. 이런 방식을 부호와 절대값방식이라고 하는데 방법은 +0 (0000 0000) -0(1000 0000) 이렇게 가지가 존재하게 되는 문제를 만듭니다. 그래서 음수를 표현할 있는 데이터형은 2 보수법이라는 알고리즘을 가지고 음수를 표현합니다

2 보수법에 대해 간략하게 알아보자면,

먼저 부분 비트를 채워줍니다. 그리고 전체 비트를 반전시켜주죠, 그리고 반전된 비트에 1 더해줍니다.

0 0 0 0  0 0 0 1 // 1 부분 비트에 입력합니다.
1 1 1 1  1 1 1 0 // 8개의 비트 전체를 1 0으로, 0 1 반전시켜줍니다.
1 1 1 1  1 1 1 1 // 반전된 비트에 1 더해줍니다. 이르면 -1 이와같은 비트로 이루어지겠죠.

-1 2 보수법으로 표현하니 1111 1111 되었습니다. 만약 1111 1111 sbyte 아닌 byte형식을 표현하기 위해 사용했다면 255 되었을 것입니다.
방법은 +0 -0이라는 혼돈을 없애주고 개를 표현할 있다는 장점에 대부분의 컴퓨터 시스템에서 음수를 표현하는 방법으로 사용되고 있습니다.

이제 음수와 양수표현에 대해서 알아보았으니, 본론으로 들어와 타입의 형변환시 발생하는 문제에대해 살펴보겠습니다. 타입에 대해 형변환이 이루어질 경우 최대 수치를 넘어갈 경우 오버플로우(Overflow), 최저값보다 작은 값을 입력할 경우 언더플로우(Underflow) 발생합니다

예를 들어 byte 255까지의 수를 담을 있습니다.
byte a 라는 변수가 있을 a 255 값을 넣어주고 +1 해주게 되면 수용할 있는 수를 넘어버리게 됩니다. 그럼 결과는 0 된답니다.
byte 가질 있는 최저값으로 돌아오게 격입니다.

어떻게 이런현상이 나오는지 이진수로 바꾸어서 보겠습니다. byte 최대값을 이진수로 바꾸면 1111 1111입니다. 여기에 1 더하게 되면
1 0000 0000 되겠지요. 하지만 byte 1바이트 , 8개의 비트만을 담을 있기때문에 넘쳐버린 비트는 버리고 오른쪽부터 8개의 비트만을 보관하게 됩니다.
그래서 최대값을 가진 변수가 오버플로우되면 0 되는것입니다. 이런 현상은 다른 모든 정수 계열 형식에도 똑같이 일어난답니다.

반대의 경우도 있습니다최저값보다 작은 데이터를 저장하게 경우 '언더 플로우(Underflow)' 발생하게 됩니다. 가령 byte형식 변수에 -1 담으려는 시도가 일어나면 실제로 변수에 255 담기게됩니다. 언더플로우나 오버플로우는는 기본적으로 조심해야 하는 현상들이기 때문에 데이터 범위와 변수의 형식을 적절하게 맞춰주는 것이 필요하답니다.

1
2
3
4
5
6
7
8
9
byte  a = 100;
 
sbyte b = (sbyte)a;
 
 
 
sbyte c = -10;
 
byte  d = (byte)c;
cs



네번째는 부동 소수점 형식과 정수 형식 사이의 변환입니다. 부동 소수점 형의 변수를 정수 형식으로 변환하면 데이터에서 소수점 아래는 버리고 소수점 위의 값만 남깁니다. 0.1 정수 변수에 변환하면 0이되고, 0.9 형변환해도 0이됩니다. 반올림과 같은 수학적 기능은 적용되지 않습니다.

1
2
3
4
5
6
7
8
9
float a = 0.9f;
 
int b = (int)a;
 
 
 
float c = 1.1f;
 
sbyte d = (sbyte)c;
cs
  



다섯번째는 문자열과 숫자 사이의 변환입니다. 문자열과 숫자는 위와 같이 형변환이 이루어지지 않습니다. 컴파일 조차 실패하게 되지요. 정수형 변환 연산자는 다른 숫자 형식 데이터로 변환하는 방법을 가지고 있긴 하지만, string 비롯한 형식으로의 형변환 방법은 갖고 있지 않습니다. 반대로 string 마찬가지이구요.
하지만 개발을 하다보면 문자열과 숫자간에 형변환이 필요할때가 많습니다. 그래서 C#에서는 이러한 형변환을 위해 정수형 부동 소수점 모두에게
'Parse()'라는 메소드를 제공합니다. 메소드에 숫자로 변환할 문자를 넘기면 숫자로 변환이 된답니다.

1
2
3
string a = "123";
 
int b = (int)c;
cs



1
2
3
int   a = int.Parse("123");
 
float b = float.Parse("1.234");
cs



이제 반대로 숫자 데이터형을 문자열로 바꾸는 방법도 있습니다. 정수 계열 데이터 형식이나 부동 소수점 데이터 형식은 object로부터 물려받은 'ToString()' 메소드를 통해
자신의 숫자를 문자열로 변환하도록 재정의 되어있습니다.

1
2
3
4
5
6
7
8
9
int    a = 1234;
 
string b = a.ToString();
 
 
 
float  c = 1.234f;
 
string d = c.ToString();
cs