Numeric conversions
Peponi │ 11/13/2024 │ 8m
Numeric conversions
Peponi
1. Introduction
C#의 숫자 형식에는 정수 형식과 부동 소수점 형식이 있다. 두 숫자 형식 간에는 암시적 또는 명시적 변환이 지원되며 명시적 변환에는 캐스트 식이 이용된다.
2. 암시적 변환
| 정수 형식 | 변환 가능 형식 |
|---|---|
| sbyte | 정수 : short, int, long, nint 실수 : 모든 실수 형식 |
| byte | 정수 : short, ushort, int, uint, long, ulong, nint, nuint 실수 : 모든 실수 형식 |
| short | 정수 : int, long, nint 실수 : 모든 실수 형식 |
| ushort | 정수 : int, uint, long, ulong, nint, nuint 실수 : 모든 실수 형식 |
| int | 정수 : long, nint 실수 : 모든 실수 형식 |
| uint | 정수 : long, ulong, nuint 실수 : 모든 실수 형식 |
| long | 실수 : 모든 실수 형식 |
| ulong | 실수 : 모든 실수 형식 |
| nint | 정수 : long 실수 : 모든 실수 형식 |
| nuint | 정수 : ulong 실수 : 모든 실수 형식 |
| 실수 형식 | 변환 가능 형식 |
|---|---|
| float | 실수 : double |
모든 정수 형식은 실수 형식으로 암시적 변환이 가능하다. 다른 형식의 값 범위 내에 있는 경우, int 형식의 상수 식 값 (정수 리터럴, const 한정자) 은 다른 숫자 형식으로 암시적 변환이 가능하다.
const int X = 500;
float Y = X;
byte Z = X; // CS0031: '500' 상수 값을 'byte`(으)로 변환할 수 없습니다.다음 변환의 경우 정밀도 손실 가능성이 있다. (자릿수 손실은 없다)
| 형식 | 변환 형식 |
|---|---|
| int, uint, long, ulong, nint, nuint | float |
| long, ulong, nint, nuint | double |
3. 명시적 변환
아래 표는 암시적 변환은 불가하지만 명시적 변환이 가능한 형식에 대한 표이다.
| 정수 형식 | 변환 가능 형식 |
|---|---|
| sbyte | byte, ushort, uint, ulong, nuint |
| byte | sbyte |
| short | sbyte, byte, ushort, uint, ulong, nuint |
| ushort | sbyte, byte, short |
| int | sbyte, byte, short, ushort, uint, ulong, nuint |
| uint | sbyte, byte, short, ushort, int, nint |
| long | sbyte, byte, short, ushort, int, uint, ulong, nint, nuint |
| ulong | sbyte, byte, short, ushort, int, uint, long, nint, nuint |
| nint | sbyte, byte, short, ushort, int, uint, ulong, nuint |
| nuint | sbyte, byte, short, ushort, int, uint, long, nint |
| 실수 형식 | 변환 가능 형식 |
|---|---|
| float | 정수 : 모든 정수 형식 실수 : decimal |
| double | 정수 : 모든 정수 형식 실수 : float, decimal |
| decimal | 정수 : 모든 정수 형식 실수 : float, double |
3.1. 정수 형식의 명시적 변환
정수 형식의 값을 다른 정수 형식으로 명시적 변환하는 경우 결과는 컨텍스트에 따라 달라진다.
checked컨텍스트 : 변환 형식 값 범위 내에 있다면 성공, 밖에 있다면 OverflowException 발생unchecked컨텍스트 : 항상 성공하지만 올바르지 않은 값으로 변환될 수 있다.-
원본 형식의 크기가 변환 형식보다 큰 경우
원본 형식의 앞쪽 비트를 잘라 변환 형식의 비트 길이에 맞춘다. 이후 남은 비트를 변환 형식의 값으로 처리한다.long testLong = 8428608; // 80 9C40, 8,428,608 short testShort = unchecked((short)testLong); // 9C40, -25536 -
원본 형식의 크기가 변환 형식보다 작은 경우
비트 처리 과정은 아래 두 케이스에 따라 달라진다. 이후 변환 형식의 값으로 처리한다.-
Signed type : 부호 확장을 한다.
부호 확장 : 원본 형식의 가장 앞 비트를 확장하는 비트에 전부 할당한다.
short testShort = -500; // FE0C, -500 uint testUInt = unchecked((uint)testShort); // FFFF FE0C, 4,294,966,796 -
Unsigned type : 제로 확장을 한다. 이 경우는 C#에서는 별로 신경 안써도 괜찮다.
제로 확장 : 확장하는 비트에 0을 전부 할당한다.
ushort testShort = 40000; // 9C40, 40000 int testInt = unchecked((int)testShort); // 9C40, 40000
-
-
원본 형식과 변환 형식의 크기가 같은 경우
변환 형식의 값으로 처리한다.
-
3.2. 실수 형식의 명시적 변환
3.2.1. 실수 -> 정수 형식 변환
정수 형식으로 변환하는 경우 소수점 자리 반올림 오류가 발생할 수 있다. (기본적으로 버림 처리한다)
double castingDouble = 1.6;
int castingInt = (int)castingDouble; // castingInt = 1
double castingDouble2 = 1.5;
int castingInt2 = (int)Math.Round(castingDouble2); // castingInt2 = 2또한, 변환할 형식 값의 범위를 벗어나는 경우에는 원본 형식의 타입과 컨텍스트에 따라 처리된다.
decimal: 컨텍스트 (checked,unchecked) 에 관계 없이 OverflowException이 발생한다.float,double:checked컨텍스트에서만 OverflowException이 발생한다.unchecked컨텍스트에서는 변환하는 정수 형식의unspecified value를 갖게 된다.
float 형식을 int 또는 uint 형식으로 변환하는 경우, 최대값을 넘지 않더라도 근처에서는 의도치 않은 동작이 발생할 수 있다. 이는 IEEE Standard 754에 정의된 float 데이터형에 의한 것이다.
3.2.2. 실수 -> 실수 형식 변환
double을 float으로 변환하는 경우 :
float형식에 맞게 반올림된다.- 만일
double값이float으로 표현하기에 너무 작거나 큰 경우,0또는∞로 처리된다.
float 또는 double을 decimal로 변환하는 경우 :
decimal형식에 맞게 반올림된다.- 만일 원본 값이
decimal로 표현하기에 너무 작은 경우에는0으로 처리된다. - 만일 원본 값이
NaN,∞또는decimal로 표현하기에 너무 큰 값인 경우에는 OverflowException이 발생한다.
decimal을 float 또는 double로 변환하는 경우 :
- 변환하는 형식에 맞게 반올림된다.