숫자 데이터 형식 사용하기
프로그래밍을 하다보면 정수 및 실수 데이터를 자주 사용합니다. 이번 강의는 숫자 데이터 형식에 대해서 알아보는 시간을 갖습니다.
> // 숫자 데이터 형식: int, long, float, double, decimal 등의 키워드로 숫자 데이터 저장
NOTE
데이터 형식(Type)이 가장 기본적인 표현 방법이지만, 데이터 형식, 데이터 유형, 자료형 등으로 표현되는 방법에 대한 차이를 줄이기 위해서 Type을 타입 또는 형식으로 표현하도록 하겠습니다. 박용준 강사의 강의에서 데이터 타입과 데이터 형식은 같은 표현입니다.
참고: 이진수 소개
다음은 컴퓨터에서 사용되는 이진수에 대한 간단한 소개입니다. 현재 진행 중인 C# 강의에서 필수적으로 다루는 내용은 아니므로, 필요에 따라 참고하시거나 생략하셔도 괜찮습니다.
숫자 데이터 형식
C#에서는 숫자 형식의 데이터를 다룰 때 사용되는 int
키워드를 포함하여 여러 가지 키워드를 제공합니다. 숫자 데이터 형식은 크게 정수 데이터 형식과 소수점을 가지는 실수 데이터 형식으로 나누며 다시 부호 있는 숫자와 부호 없는 숫자로 나눕니다.
그림: 숫자 데이터 형식
NOTE
C#에서 사용할 수 있는 많은 종류의 숫자 관련 데이터 타입은 decimal > double > float > ulong > long > uint > int > ushort > short > byte > sbyte
형태로 더 큰 수를 담을 수 있습니다.
정수 리터럴
정수 형식을 표현할 때 정수 리터럴을 사용할 수 있습니다. 기본 숫자만 사용하면 10진수로 표현되고, 숫자 앞에 0x
(Zero X)를 붙이면 16진수로 표현됩니다. C#에서는 기본적으로 8진수 리터럴을 직접 지원하지 않습니다. 대신에 10진수, 16진수 및 2진수 리터럴을 사용할 수 있습니다. 다음 코드는 작성 후 실행해보고 결과만 확인하고 넘어가면 됩니다.
코드: NumberLiteral.cs
// 정수 리터럴
using System;
class NumberLiteral
{
static void Main()
{
Console.WriteLine("{0}", 1234); // 10진수
Console.WriteLine("{0}", 0x1234); // 16진수
int octalValue = Convert.ToInt32("1234", 8); // 8진수를 10진수로 변환
Console.WriteLine("{0}", octalValue);
Console.ReadLine();
}
}
1234
4660
668
출력 결과는 10진수 1234와 16진수 1234가 10진수로 변환된 4660과 문자열 형태의 8진수 1234가 10진수로 변환된 668이 출력됩니다. 참고로, 진법 변환에 대한 내용은 이 강의에서는 따로 다루지는 않습니다. (필요하다면 Windows에 내장된 계산기(calc)의 프로그래머 옵션을 사용하세요. 계산기 사용은 비트 연산자 학습할 때 다루도록 하겠습니다.)
정수 데이터 형식 사용하기
정수형 키워드에는 s
와 u
접두사가 붙는데, 둘의 차이점은 signed
와 unsigned
의 약자로 부호가 붙느냐 안 붙느냐의 차이점입니다.
- 부호 있는(
signed
):+
,-
부호가 있는 정수형입니다. 즉, 양수와 음수를 모두 지원합니다. - 부호 없는(
unsigned
): 부호 없이+
값만을 다루는 정수형입니다. 즉 양수만을 지원합니다.
각각의 정수 데이터 형식 키워드는 그와 동일한 역할을 하는 .NET 형식을 제공하는데 예를 들어 int
형식과 동일한 형식의 .NET 데이터 형식은 System.Int32
입니다. 변수를 선언할 때도 마찬가지로 int
대신에 System.Int32
를 사용할 수 있습니다. 코드 상단에 System
네임스페이스를 using
구문으로 선언했으면 Int32
로 줄여서 표현이 가능합니다.
그림: 정수 데이터 형식 = 닷넷 형식
특별한 경우가 아니면 강의에서는 짧은 키워드를 사용하겠습니다.
정수 데이터 형식의 종류는 다음 표를 참고하세요. 8개의 키워드가 정수 데이터 형식을 표현하는데 사용됩니다.
표: 정수 데이터 형식의 종류
종류 | 키워드 | .NET 형식 |
---|---|---|
부호 있는 정수(+, -) | sbyte | System.SByte |
short | System.Int16 | |
int | System.Int32 | |
long | System.Int64 | |
부호 없는 정수(+) | byte | System.Byte |
ushort | System.UInt16 | |
uint | System.UInt32 | |
ulong | System.UInt64 |
정수형 변수 선언하고 초기화하기
변수를 공부할 때 이미 int
키워드를 사용하여 정수형 변수를 선언하는 방법을 사용하였습니다. 이번에는 정수형 변수가 가질 수 있는 최솟값과 최댓값을 저장한 후 출력하는 예제를 만들어보겠습니다.
Visual Studio에서 C# 프로젝트를 생성하고 실습하세요.
코드: IntegerDemo.cs
using System;
class IntegerDemo
{
static void Main()
{
int min = -2147483648; // 정수형이 가질 수 있는 가장 작은값
int max = +2147483647; // 정수형이 가질 수 있는 가장 큰값
Console.WriteLine("int 변수의 최솟값: {0}", min);
Console.WriteLine("int 변수의 최댓값: {0}", max);
}
}
int 변수의 최솟값: -2147483648
int 변수의 최댓값: 2147483647
int
키워드를 사용한 정수형은 최소 -21
억부터 최대 +21
억까지의 데이터를 저장하는 데 사용됩니다. 예제에서 나온 결괏값을 외울 필요는 없습니다.
숫자 구분자 사용하기
C# 7.0 버전부터는 긴 숫자를 표현할 때 언더스코어(_
) 문자를 사용하는 숫자 구분자(Digit Separator)를 제공하여 3자리마다 콤마로 구분되는 숫자 형태를 표현할 수 있습니다.
C# 인터랙티브에서 간단히 실습해봅니다.
코드: DigitSeparatorNote.cs
> // 세자라미다 콤마로 구분되는 숫자를 표현할 때 언더스코어(_) 문자로 구분 가능
> int number = 1_000_000;
> Console.WriteLine(number);
1000000
숫자 형식을 표현할 때 언더스코어(_
) 문자는 무시됩니다. 숫자 구분자를 사용하면 숫자 표시에 대한 가독성이 좋아집니다. 현재 출력 결과는 콤마를 표시하지 않았는데요. 뒤에서 출력 결과에 세자리마다 콤마를 찍는 방법도 다룹니다.
TIP
출력 결과에 세 자리마다 콤마를 넣고 싶다면, 검색 엔진이나 ChatGPT에서 'C# 세 자리마다 콤마 찍기'라는 키워드로 검색해보세요. 이런 검색과 질문 과정도 프로그래밍 능력을 키우는 데 도움이 됩니다.
부호(+
, -
) 있는 정수 데이터 형식
C#에는 +
와 -
의 정수를 다룰 수 있는 데이터 형식을 제공합니다. syte
, short
, int
, long
순서대로 작은 수부터 큰 정수까지 담아놓을 수 있습니다. sbyte
는 8비트, short
는 16비트, int
는 32비트, long
은 64비트 크기의 저장소를 사용하여 부호 있는 정수를 담을 수 있습니다.
부호 있는 정수 데이터 형식의 범위는 다음 표와 같습니다. 값의 범위를 외우거나 상세히 기억할 필요는 전혀 없으니 간단히 살펴보고 넘어가면 됩니다.
표: 부호 있는 정수의 범위
데이터 형식 | 비트 | 범위 | .NET 형식 |
---|---|---|---|
sbyte | 8 | -128 ~ 127 | System.SByte |
short | 16 | -32,768 ~ 32,767 | System.Int16 |
int | 32 | -2,147,483,648 ~ 2,147,483,647 | System.Int32 |
long | 64 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | System.Int64 |
그림: 부호 있는 정수의 범위
부호 있는 정수 데이터 형식 사용하기
부호 있는 정수 데이터 형식의 4가지 키워드를 사용해보는 예제를 작성해 보겠습니다.
다음 코드를 작성 후 실행해 보세요.
코드: SignedInteger.cs
// 부호(+, -) 있는 정수 데이터 형식: sbyte, short, int, long
using System;
class SignedInteger
{
static void Main()
{
sbyte iSByte = 127; // 8비트 부호 있는 정수형 변수 선언 및 할당
short iInt16 = 32767; // 16비트 부호 있는 정수형 변수 선언 및 할당
int iInt32 = 2147483647; // 32비트 부호 있는 정수형 변수 선언 및 할당
long iInt64 = 9223372036854775807; // 64비트 부호 있는 정수형 변수 선언 및 할당
Console.WriteLine("sbyte: {0}", iSByte);
Console.WriteLine("short: {0}", iInt16);
Console.WriteLine("int : {0}", iInt32);
Console.WriteLine("long : {0}", iInt64);
}
}
sbyte: 127
short: 32767
int : 2147483647
long : 9223372036854775807
위 코드는 sbyte
, short
, int
, long
키워드로 선언된 변수가 가질 수 있는 가장 큰 값을 할당한 후 출력하는 내용입니다.
부호 없는 정수 데이터 형식
부호 없는 정수 데이터 형식은 -
값을 사용할 수 없지만, +
값을 부호 있는 정수형의 2배 크기로 사용할 수 있는 데이터 형식을 제공합니다. 부호 없는 정수 데이터 형식은 byte
, ushort
, uint
, ulong
의 4가지 키워드를 사용합니다. 각각의 범위는 다음 표와 같이 부호 있는 범위보다 2배 더 큰 양의 정수 값을 제공합니다.
표: 부호 없는 정수의 범위
데이터 형식 | 비트 | 범위 | .NET 형식 |
---|---|---|---|
byte | 8 | 0 ~ 255 | System.Byte |
ushort | 16 | 0 ~ 65,535 | System.UInt16 |
uint | 32 | 0 ~ 4,294,967,295 | System.UInt32 |
ulong | 64 | 0 ~ 18,446,744,073,709,551,615 | System.UInt64 |
그림: 부호 없는 정수의 범위
사람의 나이는 0 ~ 255
사이의 값을 사용하기에 byte
형식은 나이를 저장할 때 유용합니다. 물론, 일반적으로는 int
형 하나로 사용합니다.
> byte age = 100;
> age
100
부호 없는 정수 데이터 형식 사용하기
부호 없는 정수 데이터 형식을 나타내는 byte
, ushort
, uint
, ulong
키워드를 사용하는 예제입니다.
코드: UnsignedInteger.cs
// 부호 없는 정수 데이터 형식: byte, ushort, uint, ulong
using System;
class UnsignedInteger
{
static void Main()
{
byte iByte = 255; // 8비트 부호 없는 정수형 변수 선언 및 할당
ushort iUInt16 = 65535; // 16비트 부호 없는 정수형 변수 선언 및 할당
uint iUInt32 = 4294967295; // 32비트 부호 없는 정수형 변수 선언 및 할당
ulong iUInt64 = 18446744073709551615; // 64비트 부호 없는 정수형 변수 선언 및 할당
Console.WriteLine("byte : {0}", iByte );
Console.WriteLine("ushort: {0}", iUInt16);
Console.WriteLine("uint : {0}", iUInt32);
Console.WriteLine("ulong : {0}", iUInt64);
}
}
byte : 255
ushort: 65535
uint : 4294967295
ulong : 18446744073709551615
위 코드는 byte
, ushort
, uint
, ulong
키워드로 선언된 변수가 가질 수 있는 가장 큰 값을 넣은 후 출력하는 내용입니다. 부호 있는 정수형보다 2배 큰 값을 넣을 수 있습니다.
정수 데이터 형식의 범위를 넘는 숫자를 넣으면 어떻게 될까요? 다음 내용을 C# 대화형에서 입력해보세요. 코드를 입력하면 "'256' 상수 값을 'byte'(으)로 변환할 수 없습니다." 에러가 표시됩니다. byte
형 변수는 0에서 255까지의 정수를 저장할 수 있어서 그보다 큰 256은 저장할 수 없습니다. Visual Studio에서는 바로 에러를 발생시켜서 이 소스는 실행이 되지 않습니다.
코드: IntegerOveflow.cs
> byte b = 256;
(1,10): error CS0031: '256' 상수 값을 'byte'(으)로 변환할 수 없습니다.
부호 있는 정수의 최솟값과 최댓값 표현하기
부호 있는 정수형 데이터 형식은 sbyte
, short
, int
, long
이 있습니다. 각각의 키워드로 생성된 변수는 해당 값의 최솟값과 최댓값 사이의 값을 저장할 수 있습니다. 각 데이터 형식이 가질 수 있는 최솟값과 최댓값은 키워드 및 .NET 형에 점을 찍었을 때 나타나는 MinValue
와 MaxValue
속성으로도 출력할 수 있습니다.
부호 있는 정수형이 가질 수 있는 최솟값과 최댓값은 다음과 같습니다.
C# 대화형에서 간단히 확인하세요. 최솟값과 최댓값의 범위는 외우지 않아도 됩니다. MinValue
와 MaxValue
속성을 이용하세요.
코드: NumberMaxMin.cs
> Console.WriteLine("[08비트] sbyte 최솟값: {0}", sbyte.MinValue);
[08비트] sbyte 최솟값: -128
> Console.WriteLine("[08비트] sbyte 최댓값: {0}", sbyte.MaxValue);
[08비트] sbyte 최댓값: 127
>
> Console.WriteLine("[16비트] short 최솟값: {0}", short.MinValue);
[16비트] short 최솟값: -32768
> Console.WriteLine("[16비트] short 최댓값: {0}", short.MaxValue);
[16비트] short 최댓값: 32767
>
> Console.WriteLine("[32비트] int 최솟값: {0}", int.MinValue);
[32비트] int 최솟값: -2147483648
> Console.WriteLine("[32비트] int 최댓값: {0}", int.MaxValue);
[32비트] int 최댓값: 2147483647
>
> Console.WriteLine("[64비트] long 최솟값: {0}", long.MinValue);
[64비트] long 최솟값: -9223372036854775808
> Console.WriteLine("[64비트] long 최댓값: {0}", long.MaxValue);
[64비트] long 최댓값: 9223372036854775807
부호 없는 정수의 최솟값과 최댓값 표현하기
부호 없는 정수형을 나타내는 .NET 형식은 System.Byte
, System.UInt16
, System.UInt32
, System.UInt64
를 사용합니다. 각각의 데이터 형식이 가지는 최솟값과 최댓값은 MinValue
와 MaxValue
속성으로 알 수 있습니다.
부호 없는 정수형이 가질 수 있는 최솟값과 최댓값은 다음과 같습니다. 부호 없는 정수형의 최솟값은 모두 0이 출력됩니다.
코드: UnsignedNumber.cs
> Console.WriteLine("[08비트] byte 최솟값: {0}", byte.MinValue);
[08비트] byte 최솟값: 0
> Console.WriteLine("[08비트] byte 최댓값: {0}", byte.MaxValue);
[08비트] byte 최댓값: 255
>
> Console.WriteLine("[16비트] ushort 최솟값: {0}", ushort.MinValue);
[16비트] ushort 최솟값: 0
> Console.WriteLine("[16비트] ushort 최댓값: {0}", ushort.MaxValue);
[16비트] ushort 최댓값: 65535
>
> Console.WriteLine("[32비트] uint 최솟값: {0}", uint.MinValue);
[32비트] uint 최솟값: 0
> Console.WriteLine("[32비트] uint 최댓값: {0}", uint.MaxValue);
[32비트] uint 최댓값: 4294967295
>
> Console.WriteLine("[64비트] ulong 최솟값: {0}", ulong.MinValue);
[64비트] ulong 최솟값: 0
> Console.WriteLine("[64비트] ulong 최댓값: {0}", ulong.MaxValue);
[64비트] ulong 최댓값: 18446744073709551615
위 코드는 .NET의 부호 없는 정수 데이터 형식별로 최솟값과 최댓값을 출력하는 예시입니다. 이를 통해 각 데이터 형식의 허용 범위를 쉽게 확인할 수 있습니다.
실수 데이터 형식 사용하기
소수점 이하의 숫자를 다루는 실수 데이터 형식(부동 소수점 데이터 형식)에 대해서 살펴보겠습니다. 부동 소수점 데이터 형식으로 표현되는 실수를 컴퓨터에서 표현하는 방법은 복잡합니다. 이러한 표현 방법에 대해서 설명하는 것은 이 강의의 범위를 벗어나기에 실수 데이터 형식은 3.14
와 같이 우리가 평상시에 사용하던 방식의 실수 그 자체로 이해하면 됩니다.
실수 데이터는 부동 소수점(double
, float
) 방식과 10진 방식(decimal
)을 다루는 3가지 데이터 형식 키워드인 double
, float
, decimal
을 제공합니다.
그림: 실수 데이터 형식
실수 데이터 형식을 나타내는 double
은 64비트, float
는 32비트, decimal
은 128비트의 크기를 갖습니다. decimal
데이터 형식은 소수점 28자리 정도까지의 자료를 다루는 금융 관련 프로그램 작성시 유용합니다.
실수 데이터 형식의 종류는 다음 표와 같습니다. 너무 어렵게 생각할 필요없이 float
, double
, decimal
키워드가 실수 데이터를 표현한다는 것만 기억하면 됩니다.
표: 실수 데이터 형식의 종류
종류 | 키워드 | .NET 형식 | 비고 |
---|---|---|---|
부동 소수점 방식 | float | System.Single | IEEE 754 단정밀도 부동 소수점 |
부동 소수점 방식 | double | System.Double | IEEE 754 배정밀도 부동 소수점 |
10진 방식 | decimal | System.Decimal |
실수 데이터 형식이 갖는 크기와 값의 범위는 아래 그림과 같습니다(정수 데이터 형식과 마찬가지로 여기에 나오는 값들의 크기와 범위는 외울 필요는 없습니다. 필요할 때 다시 찾아보면 됩니다.). 아래 표기법은 지수 표기법으로 표현했는데 float
데이터 형식의 최댓값은 약 3.4 곱하기 10의 38제곱 정도로 볼 수 있습니다.
그림: 실수 데이터 형식의 범위
표: 실수 데이터 형식의 범위
데이터 형식 | 비트 | 범위 | .NET 형식 |
---|---|---|---|
float | 32 | ±1.5 × 10^−45 ~ ±3.4 × 10^38 (7자리 정밀도) | System.Single |
double | 64 | ±5.0 × 10^−324 ~ ±1.7 × 10^308 (15-17자리 정밀도) | System.Double |
decimal | 128 | ±1.0 × 10^−28 ~ ±7.9 × 10^28 (28-29자리 정밀도) | System.Decimal |
데이터 형식 | 크기 (비트) | 최솟값 | 최댓값 |
---|---|---|---|
float | 32 | -3.4028235E+38 | +3.4028235E+38 |
double | 64 | -1.7976931348623157E+308 | +1.7976931348623157E+308 |
decimal | 128 | -79228162514264337593543950335 | +79228162514264337593543950335 |
참고: 지수 표기법
아주 큰 수와 아주 작은 수를 표현할 때에는 지수 표기법(exponential notation)을 사용합니다. 지수 표기법은 과학적 표기법(scientific notation)이라고도 합니다. 지수 표기법은 아주 크거나 아주 작은 숫자들을 십진법으로 편하게 작성하여 표현하는 방법입니다. 예를 들어, 숫자 12345678901은 1.23E+10으로 표시하며, 이는 1.23 곱하기 10의 10제곱(승)입니다. 지수 표기법은 숫자를 "-d.ddd…E+ddd" 또는 "-d.ddd…e+ddd" 형태의 문자열로 변환합니다. 여기서 각 "d"는 숫자(0-9)를 나타냅니다. 숫자가 음수이면 문자열 앞에 빼기 기호가 붙습니다. 소수점 앞에는 항상 숫자가 하나만 있어야 합니다.
실수E+지수
: 실수 곱하기 지수만큼의 10의 거듭제곱을 나타냅니다.-3.4E+38
: -3.4 곱하기 10의 38제곱입니다.1.7E+308
: 1.7 곱하기 10의 308제곱입니다.
double 키워드(System.Double)
double
데이터 형식은 64비트 실수 데이터를 저장할 수 있습니다. double
변수에 실수 데이터를 입력하면 기본값으로 double
데이터 형식이 됩니다. double
데이터 형식에 대해서 명확하게 설정을 할 때에는 실수 데이터 값 뒤에 접미사로 대문자 D
또는 소문자 d
를 지정하여 double d = 100D;
형태를 사용합니다.
실수 데이터 선언 및 초기화
간단히 원주율을 저장해 놓고 출력하는 예제를 다음과 같이 입력한 후 실행해보세요.
코드: DoubleDemo.cs
// double 키워드: 실수형 데이터 형식(64비트 부동 소수점 숫자)
using System;
class DoubleDemo
{
static void Main()
{
double PI = 3.141592; // 배정밀도 부동 소수점 변수를 선언하고 값을 할당
Console.WriteLine("{0}", PI); // 3.141592
}
}
3.141592
팁: Double.MaxValue와 Double.MinValue
double
데이터 형식이 가질 수 있는 최솟값과 최댓값은 .NET 형식인 Double
의 MinValue
속성과 MaxValue
속성으로 구할 수 있습니다.
코드: DoubleMinMax.cs
> double min = Double.MinValue; // double 형의 최솟값
> min
-1.7976931348623157E+308
> double max = Double.MaxValue; // double 형의 최댓값
> max
1.7976931348623157E+308
참고: int
형식에 실수 데이터 입력 시도
실수 자료는 int
형식 변수에 값을 넣을 수 없습니다. 예를 들어 다음 예제 코드와 같이 int
형식 변수인 number
에 값 3.14를 넣으려고 하면 에러가 발생합니다. 3.14는 실수 자료형이라 정수형 변수에 담을 수 없습니다.
> int number = 3.14;
(1,14): error CS0266: 암시적으로 'double' 형식을 'int' 형식으로 변환할 수 없습니다. 명시적 변환이 있습니다. 캐스트가 있는지 확인하세요.
float 키워드(System.Single)
float
데이터 형식은 32비트 부동 소수점 방식을 사용합니다. 간단히 실수 데이터를 저장하고 출력하는 예제를 아래와 같이 입력한 후 실행해 보세요.
코드: FloatDemo.cs
// float 키워드: 실수형 데이터 형식(32비트 부동 소수점 숫자)
using System;
class FloatDemo
{
static void Main()
{
float f = 99.99F; // 단정밀도 부동 소수점 변수를 선언하고 값을 할당
Console.WriteLine("{0}", f); // 99.99
}
}
99.99
float
키워드를 사용하여 실수 데이터를 직접 입력할 때에는 대문자 F
또는 소문자 f
를 접미사를 사용하여 대입하여야 합니다. 접미사를 사용하지 않을 경우에는 실숫값을 기본적으로 double
형으로 인식하여 float
형 변수에 담을 수 없습니다. 그래서 float
형 변수를 선언할 때에는 접미사로 F
를 붙여야 합니다.
팁: Single.MaxValue
와 Single.MinValue
float
데이터 형식의 최솟값과 최댓값은 Single
데이터 형식의 MinValue
와 MaxValue
속성을 통해서 구할 수 있습니다.
> Single.MaxValue
3.40282347E+38
> Single.MinValue
-3.40282347E+38
파이썬 예제: float()
함수로 실수로 변환하기
코드: FloatFunction.py
>>> # float() 함수로 실수로 변환하기
>>> ## 정수를 실수로 변환
>>> (float(1234)) # 1234.0
1234.0
>>> ## 계산식을 실수로 변환
>>> (float(12 + 34)) # 4
## 6.0
4
## 6.0
>>> ## 숫자 모양의 문자열을 실수로 변환
>>> (float('3.14')) # 3.14
3.14
decimal
키워드(System.Decimal
)
decimal
키워드는 실수 형식의 데이터를 다룰 때 사용되는데, 2진수 체계로 처리되는 double
과 float
와 달리 10진수로 표현합니다. decimal
의 크기는 128비트의 숫자를 표현할 수 있습니다. float
와 double
데이터 형식에 비해서 가장 정밀도가 높은 정확한 자료를 담을 수 있습니다. 값 자체의 범위는 float
와 double
데이터 형식에 비해서 작지만, 소수점 28자리까지의 정확도(유효 자릿수)를 가지기에 세금과 환율 계산 등의 금융 프로그램을 작성하는데 주로 사용됩니다. decimal
키워드로 선언된 변수에 숫자 리터럴을 입력할 때에는 반드시 대문자 M
또는 소문자 m
접미사를 사용해야 합니다. 돈(Money)을 다루는 금융 및 회계 프로그램의 숫자 형식에는 decimal
형식을 권장합니다.
다음 참고용 샘플 코드를 보면 실수는 부동소수점 수를 2진수로 표현하기에 소수점 처리에 오류가 발생합니다. 이러한 경우에는 decimal
형식을 사용하여 오차가 발생하지 않도록 해야합니다.
> (2.0 - 1.1)
0.89999999999999991
> Convert.ToDecimal(2.0 - 1.1)
0.9
다음은 접미사를 사용하였습니다.
> 2.0m - 1.1m // decimal 리터럴로 계산하여 오차가 발생하지 않습니다
0.9
다음 샘플 코드처럼 decimal.TryParse()
메서드를 사용하면 숫자 형식의 문자열을 decimal
형태로 변환하여 decimal
변수에 담을 수 있는 기능을 제공합니다. TryParse()
메서드의 2번째에는 out
키워드가 사용되었는데요. 이러한 내용은 뒤에서 좀 더 자세히 다루니 지금은 샘플 코드만 살펴보면 됩니다.
> decimal d = 0M; // deciaml 리터럴 0M으로 변수 d를 초기화
> decimal.TryParse("12.34", out d); // "12.34"를 변환한 결과를 변수 d에 전달
> d
12.34
실수(Decimal) 데이터 사용하기
실수 데이터를 decimal
변수에 넣어놓고 출력하는 예제를 다음과 같이 작성 후 실행해 보세요.
코드: DecimalDemo.cs
// decimal 키워드: 실수형 데이터 형식(128비트 10진수)
using System;
class DecimalDemo
{
static void Main()
{
decimal d = 12.34M; // decimal 변수 선언 후 실수 데이터 저장
Console.WriteLine("{0}", d); // 12.34
}
}
12.34
참고 Java – BigDecimal
타입
자바 환경에서는, 카드사 등의 금액을 연산하는 업계에서는 자바의 BigDecimal
타입을 사용합니다.
팁: Decimal.MaxValue와 Decimal.MinValue
decimal 데이터 형식 역시 .NET 데이터 형식인 Decimal
의 MinValue
와 MaxValue
속성을 통해서 구할 수 있습니다.
코드: DecimalMinMax.cs
> decimal.MaxValue
79228162514264337593543950335
> System.Decimal.MinValue
-79228162514264337593543950335
숫자 형식의 리터럴 값에 접미사 붙이기
정수형 데이터를 표현하는 리터럴을 만들 때에는 접미사를 붙여서 사용할 수 있습니다. int
형은 따로 붙이지 않고 대문자 L
과 소문자 l
을 정수형에 접미사로 붙이면 long
형을 나타냅니다. U
와 u
를 접미사로 붙이면 uint
를 UL
과 ul
을 접미사로 붙이면 ulong
형을 나타냅니다.
실수형 데이터를 표현하는 리터럴을 만들 때에도 접미사를 사용할 수 있습니다. F
또는 f
를 붙이면 float
형을 나타내고 D
또는 d
는 double
형을 나타냅니다. M
또는 m
은 decimal
형을 나타내는 접미사입니다.
숫자 데이터 형식에 접미사 붙이기
이러한 정수형과 실수형을 나타내는 접미사는 대문자 접미사를 사용하면 눈에 보기 편할 수 있습니다.
코드: RealNumberPractice.cs
> float f = 3.14F;
> double d = 3.14D;
> decimal m = 3.14M;
> Console.WriteLine("{0}, {1}, {2}", f, d, m);
3.14, 3.14, 3.14
C#에서 리터럴의 타입은 기본적으로 정수형(int
)이나 실수형(double
)일 수 있습니다. 그러나 리터럴의 타입을 명시적으로 지정할 수도 있습니다.
리터럴 타입과 변수 타입이 일치하지 않을 때, 일반적으로 형변환이 필요한데 이는 자동 형변환(암시적 형변환)이나 명시적 형변환을 사용하여 수행됩니다.
long a = 1234;
이 경우, 리터럴은int
타입이고 변수는long
타입입니다.int
에서long
으로의 형변환이 자동으로 일어나기 때문에 에러가 발생하지 않습니다.long a = 1234L;
이 경우, 리터럴은long
타입이므로 이미 변수 타입과 일치합니다.float f = 12.34;
이 경우, 리터럴은double
타입이고 변수는float
타입입니다.double
에서float
형식으로 형변환 시 정보 손실이 발생할 수 있으므로 명시적 형변환이 필요합니다.float f = 12.34F;
이 경우, 리터럴은float
타입이므로 변수 타입과 일치합니다.byte b = 123;
이 경우, 리터럴은int
타입이고 변수는byte
타입입니다.byte
의 허용 범위는 0 ~ 255이므로, 리터럴 값이byte
의 범위 내에 있기 때문에 자동으로 형변환되어 에러가 발생하지 않습니다.
결론적으로, 변수 선언부의 데이터 타입과 리터럴 타입이 항상 일치할 필요는 없습니다. 자동 형변환이 가능한 경우에는 암시적 형변환이 이루어질 수 있고, 그렇지 않은 경우 명시적 형변환을 사용하여 데이터 타입을 변환할 수 있습니다.
실수 데이터 형식의 최솟값과 최댓값 표현하기
실수 데이터 형식을 다루는 float
, double
, decimal
의 최솟값과 최댓값을 표현하는 방법을 함께 살펴보도록 하겠습니다. 각각의 키워드에 MinValue
와 MaxValue
상수를 요청하면 됩니다.
다음과 같이 코드를 입력한 후 실행해 보세요.
코드: NumberDemo.cs
> // float: 32비트
> Console.WriteLine("float 최솟값: {0}", float.MinValue);
float 최솟값: -3.402823E+38
> Console.WriteLine("float 최댓값: {0}", float.MaxValue);
float 최댓값: 3.402823E+38
>
> // double: 64비트
> Console.WriteLine("double 최솟값: {0}", double.MinValue);
double 최솟값: -1.79769313486232E+308
> Console.WriteLine("double 최댓값: {0}", double.MaxValue);
double 최댓값: 1.79769313486232E+308
>
> // decimal: 128비트
> decimal min = Decimal.MinValue;
> decimal max = Decimal.MaxValue;
> Console.WriteLine("decimal 최솟값: {0}", min);
decimal 최솟값: -79228162514264337593543950335
> Console.WriteLine("decimal 최댓값: {0}", max);
decimal 최댓값: 79228162514264337593543950335
숫자 데이터 형식은 MinValue
와 MaxValue
상수를 통해서 각 데이터 형식의 최솟값과 최댓값을 구할 수 있습니다.
널 가능 형식(Nullable Type)
C# 2.0에서 처음 소개된 널 가능 형식에 대해서 살펴보겠습니다. 숫자 형식의 변수를 선언할 때 int?
, double?
형태로 ?
(물음표) 기호를 붙이면 널 가능 형식으로 변경이 됩니다. 이러한 널 가능 형식에는 아무런 값도 없음을 의미하는 null
을 대입할 수 있습니다.
코드: NullableDemo.cs
> int? x = null; // 널 가능 형식
> x
null
> double? d = null;
> d
null
널(Null)에 대한 좀 더 자세한 내용은 널(Null) 다루기 강의에서 다룹니다.
참고: 진법 표현과 변환
C#은 10진법, 16진법, 8진법 숫자를 다룰 수 있습니다.
10진법은 우리가 일상생활에서 가장 흔히 사용하는 숫자 체계로, 0부터 9까지의 숫자로 구성됩니다. C#에서는 10진법 숫자를 별도의 접두사 없이 그대로 사용할 수 있습니다. 예를 들어, 다음과 같이 선언할 수 있습니다.
> int decimalNumber = 10;
> decimalNumber
10
16진법은 0부터 9까지의 숫자와 A(10)부터 F(15)까지의 알파벳을 사용하여 수를 표현하는 체계입니다. C#에서는 16진법 숫자를 나타내기 위해 숫자 앞에 0x
또는 0X
접두사를 붙입니다. 예를 들어, 다음 코드는 16진법으로 표현된 값을 10진법으로 해석했을 때 42에 해당하는 숫자를 저장합니다.
> int hexNumber = 0x2A; // 10진법으로 42
> hexNumber
42
C#에서는 8진법 리터럴을 직접적으로 지원하지 않습니다. 그러나 문자열 형태로 8진수를 표현한 후, 이를 10진법 값으로 변환하는 방법을 사용할 수 있습니다. 이때, Convert.ToInt32(string, int)
메서드를 활용하면 문자열로 표현된 8진수를 10진수로 변환할 수 있습니다. 예를 들어, 아래 코드에서는 8진법 문자열 "24"
를 10진법 숫자 20
으로 변환합니다.
> int octalNumber = Convert.ToInt32("24", 8); // 10진법으로 20
> octalNumber
20
C#에서는 Convert.ToInt32
와 Convert.ToString
등의 메서드를 활용하여 숫자 간 진법 변환을 쉽게 수행할 수 있습니다. 예를 들어, 16진법 숫자를 10진법 문자열로 변환하려면 다음과 같이 작성할 수 있습니다.
> int hexValue = 0x2A;
> string decimalString = Convert.ToString(hexValue, 10); // "42"
> decimalString
"42"
반대로, 10진법 숫자를 16진법 문자열로 변환하려면 다음과 같이 작성합니다.
> int decimalValue = 42;
> string hexString = Convert.ToString(decimalValue, 16); // "2a"
> hexString
"2a"
장 요약
숫자 데이터 형식을 나타내는 키워드는 많이 있지만, 가장 많이 사용되는 것은 int
, long
, float
, double
, decimal
입니다. 그리고 모든 숫자 데이터 형식은 최댓값과 최솟값을 제공하지만 범위를 외우거나할 필요는 없습니다. 프로그램을 작성하면서 자연스럽게 각각의 범위에 맞는 데이터 형식을 사용하는 법을 익힐 수가 있습니다.
1.1 퀴즈
(1) 다음 중 자료형의 크기가 올바르지 않은 것을 고르세요.
a. sbyte
: 4비트
b. short
: 16비트
c. int
: 32비트
d. long
: 64비트
정답: a
sbyte
는 8비트(1바이트) 크기를 가집니다.
(2) 다음 중 정수형 자료형의 최대값으로 올바르지 않은 것을 고르세요.
a. byte
: 255
b. short
: 65535
c. int
: 2147483647
d. uint
: 4294967295
정답: b
short
정수형의 최댓값은 32,767이며,ushort
는 65,535까지 표현할 수 있습니다.
(3) int
형 정수의 최댓값을 출력하는 명령어는 무엇인가요?
정답:
System.Int32.MaxValue
int.MaxValue
정수형 데이터 타입은
MaxValue
와MinValue
속성을 통해 최댓값과 최솟값을 확인할 수 있습니다.
int.MaxValue
→2147483647
int.MinValue
→-2147483648
(4) 다음 중 자료형의 크기가 올바르지 않은 것을 고르세요.
a. float
: 16비트
b. int
: 32비트
c. double
: 64비트
d. decimal
: 128비트
정답: a
float
은 32비트(4바이트) 크기를 가집니다.
자료형 크기 정리
float
→ 32비트double
→ 64비트decimal
→ 128비트
(5) 다음 중 실수형 자료를 표현할 때 사용하는 표기법 중 올바르지 않은 것을 고르세요.
a. float f = 3.14F;
b. double d = 3.14;
c. double d = 3.14D;
d. decimal d = 3.14D;
정답: d
decimal
자료형은D
가 아니라M
(또는m
) 접미사를 사용해야 합니다.- 올바른 표현:
decimal d = 3.14M;
1.2 연습문제: 정수의 최솟값과 최댓값 출력
다음 소스 코드를 완성하여 정수형의 최솟값(-2147483648
)과 최댓값(2147483647
)이 출력되도록 하세요.
코드
using System;
class IntegerPractice
{
static void Main()
{
//[1] int 데이터 형식의 최솟값
Console.WriteLine("{0}", int.MinValue);
//[2] int 데이터 형식의 최댓값
Console.WriteLine("{0}", int.MaxValue);
}
}
실행 결과
-2147483648
2147483647
정답
(1) int.MinValue 또는 Int32.MinValue
(2) int.MaxValue 또는 Int32.MaxValue
해설
int
또는System.Int32
자료형은MinValue
와MaxValue
속성을 이용해 최솟값과 최댓값을 확인할 수 있습니다.int.MinValue
→-2147483648
int.MaxValue
→2147483647
- 동일한 표현으로
Int32.MinValue
및Int32.MaxValue
를 사용할 수도 있습니다.