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
로 변환하는 경우 :
- 변환하는 형식에 맞게 반올림된다.