정수 자료형의 종류와 크기는 다음과 같다.
| 자료형 | 설명 | 크기(byte) | 범위 |
|---|---|---|---|
byte |
부호 없는 정수 | 1 byte | 0 ~ 255 |
sbyte |
정수 | 1 byte | -128 ~ 127 |
short |
정수 | 2 byte | -32,768 ~ 32,767 |
ushort |
부호 없는 정수 | 2 byte | 0 ~ 65,535 |
int |
정수 | 4 byte | -2,147,483,648 ~ 2,147,483,647 |
uint |
부호 없는 정수 | 4 byte | 0 ~ 4,294,967,295 |
long |
정수 | 8 byte | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
ulong |
부호 없는 정수 | 8 byte | 0 ~ 18,446,744,073,709,551,615 |
char |
유니코드 문자 | 2 byte |
using System;
namespace IntegralTypes
{
class MainApp
{
static void Main(string[] args)
{
sbyte sb = -10;
byte b = 40;
Console.WriteLine($"sb = {sb}, b = {b}");
short s = -30000;
ushort us = 60000;
Console.WriteLine($"s = {s}, us = {us}");
int i = -10000000;
uint ui = 300000000;
Console.WriteLine($"i = {i}, ui = {ui}");
long l = -500000000000;
ulong ul = 2000000000000000000;
Console.WriteLine($"l = {l}, ul = {ul}");
}
}
}
sb = -10, b = 40
s = -30000, us = 60000
i = -10000000, ui = 300000000
l = -500000000000, ul = 2000000000000000000
unsigned 정수형만약 음수를 저장할 필요가 없다면, 같은 공간으로 2배의 범위를 지정할 수 있는 unsigned 정수형을 고려해 볼 수 있다.
byte : 0 ~ 255ushort : 0 ~ 65,535uint : 0 ~ 4,294,967,295ulong : 0 ~ 18,446,744,073,709,551,615signed 방식은 가장 왼쪽의 비트를 이용해 부호 표시를 하지만,
unsigned 방식은 가장 왼쪽의 비트도 범위를 표현하는데 사용한다.

signed 방식에서는 가장 왼쪽의 비트가 0 이면 양수, 1 이면 음수를 표현한다.
000010100 = 20 (16 + 4)10010100 = -108 (-128 + 16 + 4)using System;
namespace IntegralTypes
{
class MainApp
{
static void Main(string[] args)
{
byte a = 0b10010100; // 148 = (128 + 16 + 4)
Console.WriteLine($"a = {a}");
sbyte b = (sbyte)a; // -108 = (-128 + 16 + 4)
Console.WriteLine($"b = {b}");
}
}
}
a = 148
b = -108
컴퓨터에서 음의 정수를 표현할 때에는 2의 보수를 취해야 한다. 2의 보수법은 다음과 같은 과정을 거친다.

정수 +5 와 -5 를 더했을 때 0 이 되는 것을 확인할 수 있다.

변수는 데이터를 담는 그릇과 같다. 그릇에 용량 이상의 물을 담으면 넘치는 것처럼, 변수에도 데이터 형식의 크기를 넘어선 값을 담으면 넘친다. 이러한 현상을 오버플로(Overflow) 라고 한다.
byte 형 변수 a 에 byte 가 담을 수 있는 최대값을 저장하고 a 에 1 을 더해보도록 하겠다.
using System;
namespace IntegralTypes
{
class MainApp
{
static void Main(string[] args)
{
byte a = byte.MaxValue;
Console.WriteLine($"a = {a}");
a = (byte)(a + 1);
Console.WriteLine($"a = {a}");
}
}
}
a = 255
a = 0
오버플로된 변수 a 는 byte 가 가질 수 있는 최저값 0 을 갖는다.
이는 수를 2진수로 바꿔보면 쉽게 이해할 수 있다.
byte 의 최대값은 255 이며, 255는 2진수로 바꾸면 1111 1111 이다.

여기에 1 을 더하면 1 0000 0000 이 된다. 그러나 byte 는 8개의 비트만 담을 수 있으므로 넘쳐 흐른 왼쪽의 비트는 버리고 오른쪽 8개 비트 0000 0000 만 보관하게 된다.

위 처럼 각 데이터 형식의 최대값을 넘어가는 데이터를 저장할 때는 오버플로가 일어나지만 최저값보다 작은 데이터를 저장하면 언더플로(Underflow) 가 일어난다.
byte 형식 변수에 -1 을 담으려하면 실제로는 255 가 저장된다.
using System;
namespace IntegralTypes
{
class MainApp
{
static void Main(string[] args)
{
sbyte a = -1;
Console.WriteLine($"a = {a}");
byte b = (byte)a;
Console.WriteLine($"b = {b}");
}
}
}
a = -1
b = 255
실수 자료형의 종류와 크기는 다음과 같다.
| 데이터 형식 | 설명 | 크기(byte) | 범위 |
|---|---|---|---|
float |
단일 정밀도 부동 소수점 형식 | ||
| (7개의 자릿수만 다룰 수 있음) | 4 btye | -3.402823 * 10^(38) ~ | |
| 3.402823 * 10^(38) | |||
double |
복수 정밀도 부동 소수점 형식 | ||
| (15~16개의 자릿수를 다룰 수 있음) | 8 byte | -1.79769313486232 * 10^(308) ~ 1.79769313486232 * 10^(308) |
using System;
namespace FloatingPoint
{
class MainApp
{
static void Main(string[] args)
{
float a = 3.14159265358979323846f;
Console.WriteLine(a);
double b = 3.14159265358979323846;
Console.WriteLine(b);
}
}
}
3.1415927
3.141592653589793
float 형 선언 시 숫자 뒤에 f 를 붙여야 하며, float 과 double 은 자신의 가수부가 담을 수 있는
부분까지만 저장하고 나머지는 버린다.
C#의 실수형은 IEEE 754 라는 표준 알고리즘에 기반한 데이터 형식으로 실수를 저장하기 위해
소수점 . 을 유동적으로 움직여서 표현한다.
이를 위해 비트 공간을 아래와 같이 사용한다.

float 형 맨 왼쪽 1비트를 부호, 그 다음 8비트를 지수, 그 다음 23비트를 가수부로 사용한다.
double 형 맨 왼쪽 1비트를 부호, 그 다음 11비트를 지수, 그 다음 52비트를 가수부로 사용한다.
이 과정에서 저장 공간은 한정되어 있기 때문에 소수점 절삭으로 인한 오차가 발생한다. 따라서 실수형은 항상 '근삿값'이라는 것을 기억해야 한다.
decimal 형식decimal 도 실수를 다루는 데이터 형식으로 위의 부동 소수점과는 다른 방식으로 소수를 다루며
정밀도가 훨씬 높다.
| 데이터 형식 | 설명 | 크기 (btye) | 범위 |
|---|---|---|---|
decimal |
29자리 데이터를 표현할 수 있는 | ||
| 소수 형식 | 16 byte | 약 ± 1.0 * 10^(-28) ~ ± 7.9 * 10^28 |
using System;
namespace Decimal
{
class MainApp
{
static void Main(string[] args)
{
float a = 3.141592653589793238462643383279f;
Console.WriteLine(a);
double b = 3.141592653589793238462643383279;
Console.WriteLine(b);
decimal c = 3.141592653589793238462643383279m;
Console.WriteLine(c);
}
}
}
3.1415927
3.141592653589793
3.1415926535897932384626433833
decimal 형 선언 시 숫자 뒤에 m 을 붙여야 한다.
char 형식은 정수를 다루는 데이터 형식이지만, 수가 아닌 'a', 'b', 'c' 와 같은 문자 데이터를 다룬다.
작은 따옴표 '' 로 문자를 감싸줘야 한다.
using System;
namespace Char
{
class MainApp
{
static void Main(string[] args)
{
char a = 'H';
char b = 'E';
char c = 'L';
char d = 'L';
char e = 'O';
Console.Write(a);
Console.Write(b);
Console.Write(c);
Console.Write(d);
Console.Write(e);
}
}
}
HELLO
string 형식은 여러 개의 문자 형식을 하나로 묶어 처리하며, 정해진 크기나 담을 수 있는 데이터의
범위가 따로 정해져 있지 않다.
큰 따옴표 "" 로 문자열 데이터를 감싸줘야 한다.
using System;
namespace String
{
class MainApp
{
static void Main(string[] args)
{
string a = "HELLO";
Console.Write(a);
}
}
}
HELLO
\\n 을 통해 줄 바꿈을 할 수 있으며, 큰 따옴표 3개를 붙여 쓰면 """...""" 여러 줄로 이어진 문자열
리터럴을 만들 수 있다.
using System;
namespace MultiLine
{
class MainApp
{
static void Main(string[] args)
{
string a = "Hello\\nWorld!\\n";
Console.WriteLine(a);
string b = """
동해물과 백두산이
마르고 닳도록
하느님이 보우하사
우리나라 만세
""";
Console.WriteLine(b);
}
}
}
Hello
World!
동해물과 백두산이
마르고 닳도록
하느님이 보우하사
우리나라 만세
string 형식은 문자열을 담는 역할을 할 뿐 아니라, 문자열을 가공하기 위한 다양한 기능도
함께 제공한다.