Favicon

Numeric conversions

Peponi11/13/20248m

C#
SyntaxTypeCasting

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, nuintfloat
long, ulong, nint, nuintdouble

3. 명시적 변환

아래 표는 암시적 변환은 불가하지만 명시적 변환이 가능한 형식에 대한 표이다.

정수 형식변환 가능 형식
sbytebyte, ushort, uint, ulong, nuint
bytesbyte
shortsbyte, byte, ushort, uint, ulong, nuint
ushortsbyte, byte, short
intsbyte, byte, short, ushort, uint, ulong, nuint
uintsbyte, byte, short, ushort, int, nint
longsbyte, byte, short, ushort, int, uint, ulong, nint, nuint
ulongsbyte, byte, short, ushort, int, uint, long, nint, nuint
nintsbyte, byte, short, ushort, int, uint, ulong, nuint
nuintsbyte, byte, short, ushort, int, uint, long, nint
실수 형식변환 가능 형식
float정수 : 모든 정수 형식
실수 : decimal
double정수 : 모든 정수 형식
실수 : float, decimal
decimal정수 : 모든 정수 형식
실수 : float, double

3.1. 정수 형식의 명시적 변환

정수 형식의 값을 다른 정수 형식으로 명시적 변환하는 경우 결과는 컨텍스트에 따라 달라진다.

  • checked 컨텍스트 : 변환 형식 값 범위 내에 있다면 성공, 밖에 있다면 OverflowException 발생
  • unchecked 컨텍스트 : 항상 성공하지만 올바르지 않은 값으로 변환될 수 있다.
    1. 원본 형식의 크기가 변환 형식보다 큰 경우
      원본 형식의 앞쪽 비트를 잘라 변환 형식의 비트 길이에 맞춘다. 이후 남은 비트를 변환 형식의 값으로 처리한다.

      long testLong = 8428608;                              // 80 9C40, 8,428,608
      short testShort = unchecked((short)testLong);         // 9C40, -25536
    2. 원본 형식의 크기가 변환 형식보다 작은 경우
      비트 처리 과정은 아래 두 케이스에 따라 달라진다. 이후 변환 형식의 값으로 처리한다.

      • 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. 원본 형식과 변환 형식의 크기가 같은 경우
      변환 형식의 값으로 처리한다.

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. 실수 -> 실수 형식 변환

doublefloat으로 변환하는 경우 :

  • float 형식에 맞게 반올림된다.
  • 만일 double 값이 float으로 표현하기에 너무 작거나 큰 경우, 0 또는 로 처리된다.

float 또는 doubledecimal로 변환하는 경우 :

  • decimal 형식에 맞게 반올림된다.
  • 만일 원본 값이 decimal로 표현하기에 너무 작은 경우에는 0으로 처리된다.
  • 만일 원본 값이 NaN, 또는 decimal로 표현하기에 너무 큰 값인 경우에는 OverflowException이 발생한다.

decimalfloat 또는 double로 변환하는 경우 :

  • 변환하는 형식에 맞게 반올림된다.

4. 참조 자료