산술 연산자(C# 참조)

다음 연산자는 숫자 형식 피연산자를 포함한 산술 작업을 수행합니다.

해당 연산자는 모든 정수부동 소수점 숫자 형식을 지원합니다.

정수 형식의 경우 이러한 연산자(++-- 연산자 제외)는 int, uint, longulong 형식에 대해 정의됩니다. 피연산자가 다른 정수 형식(sbyte, byte, short, ushort 또는 char)인 경우, 해당 값은 연산의 결과 형식이기도 한 int 형식으로 변환됩니다. 피연산자가 정수 형식 또는 부동 소수점 형식인 경우 해당 형식이 있으면 값은 가장 근사한 포함하는 형식으로 변환됩니다. 자세한 내용은 C# 언어 사양숫자 승격 섹션을 참조하세요. ++-- 연산자는 모든 정수 형식 및 부동 소수점 숫자 형식과 char 형식에 대해 정의됩니다. 복합 할당 식의 결과 형식은 왼쪽 피연산자의 형식입니다.

증가 연산자 ++

단항 증가 연산자(++)는 피연산자를 1씩 증가합니다. 피연산자는 변수, 속성 액세스 또는 인덱서 액세스여야 합니다.

증가 연산자는 후위 증가 연산자 x++ 및 전위 증가 연산자 ++x라는 두 가지 양식으로 지원됩니다.

후위 증가 연산자

x++의 결과는 다음 예제와 같이 연산 ‘전’ x의 값입니다.

int i = 3;
Console.WriteLine(i);   // output: 3
Console.WriteLine(i++); // output: 3
Console.WriteLine(i);   // output: 4

후위 증가 연산자

++x의 결과는 다음 예제와 같이 연산 ‘후’ x의 값입니다.

double a = 1.5;
Console.WriteLine(a);   // output: 1.5
Console.WriteLine(++a); // output: 2.5
Console.WriteLine(a);   // output: 2.5

감소 연산자 --

단항 감소 연산자(--)는 피연산자를 1씩 감소합니다. 피연산자는 변수, 속성 액세스 또는 인덱서 액세스여야 합니다.

감소 연산자는 후위 감소 연산자 x-- 및 전위 감소 연산자 --x라는 두 가지 양식으로 지원됩니다.

후위 감소 연산자

x--의 결과는 다음 예제와 같이 연산 ‘전’ x의 값입니다.

int i = 3;
Console.WriteLine(i);   // output: 3
Console.WriteLine(i--); // output: 3
Console.WriteLine(i);   // output: 2

후위 감소 연산자

--x의 결과는 다음 예제와 같이 연산 ‘후’ x의 값입니다.

double a = 1.5;
Console.WriteLine(a);   // output: 1.5
Console.WriteLine(--a); // output: 0.5
Console.WriteLine(a);   // output: 0.5

단항 더하기 및 빼기 연산자

단항 + 연산자는 피연산자의 값을 반환합니다. 단항 - 연산자는 피연산자의 숫자 부정을 계산합니다.

Console.WriteLine(+4);     // output: 4

Console.WriteLine(-4);     // output: -4
Console.WriteLine(-(-4));  // output: 4

uint a = 5;
var b = -a;
Console.WriteLine(b);            // output: -5
Console.WriteLine(b.GetType());  // output: System.Int64

Console.WriteLine(-double.NaN);  // output: NaN

단항 - 연산자는 ulong 형식을 지원하지 않습니다.

곱하기 연산자 *

곱하기 연산자 *는 피연산자의 곱을 계산합니다.

Console.WriteLine(5 * 2);         // output: 10
Console.WriteLine(0.5 * 2.5);     // output: 1.25
Console.WriteLine(0.1m * 23.4m);  // output: 2.34

단항 * 연산자는 포인터 간접 참조 연산자입니다.

나누기 연산자 /

나누기 연산자 /는 오른쪽 피연산자로 왼쪽 피연산자를 나눕니다.

정수 나누기

정수 형식의 피연산자의 경우 / 연산자의 결과는 정수 형식이고 두 피연산자의 몫과 동일한 값은 0으로 반올림됩니다.

Console.WriteLine(13 / 5);    // output: 2
Console.WriteLine(-13 / 5);   // output: -2
Console.WriteLine(13 / -5);   // output: -2
Console.WriteLine(-13 / -5);  // output: 2

두 피연산자의 몫을 부동 소수점 숫자로 가져오려면 float, double 또는 decimal 형식을 사용하세요.

Console.WriteLine(13 / 5.0);       // output: 2.6

int a = 13;
int b = 5;
Console.WriteLine((double)a / b);  // output: 2.6

부동 소수점 나누기

float, doubledecimal 형식의 경우 / 연산자의 결과는 두 피연산자의 몫입니다.

Console.WriteLine(16.8f / 4.1f);   // output: 4.097561
Console.WriteLine(16.8d / 4.1d);   // output: 4.09756097560976
Console.WriteLine(16.8m / 4.1m);   // output: 4.0975609756097560975609756098

피연산자 중 하나가 decimal이면 float 또는 double 모두 decimal로 암시적으로 변환할 수 없기 때문에 나머지 피연산자는 float 또는 double일 수 없습니다. float 또는 double 피연산자를 decimal 형식으로 암시적으로 변환해야 합니다. 숫자 형식 간의 변환에 대한 자세한 내용은 기본 제공 숫자 변환을 참조하세요.

나머지 연산자 %

나머지 연산자 %는 왼쪽 피연산자를 오른쪽 피연산자로 나눈 후 나머지를 계산합니다.

정수 나머지

정수 형식의 피연산자의 경우 a % b의 결과가 a - (a / b) * b에서 생성된 값입니다. 다음 예와 같이 0이 아닌 나머지의 부호는 왼쪽 피연산자의 부호와 동일합니다.

Console.WriteLine(5 % 4);   // output: 1
Console.WriteLine(5 % -4);  // output: 1
Console.WriteLine(-5 % 4);  // output: -1
Console.WriteLine(-5 % -4); // output: -1

Math.DivRem 메서드를 사용하여 정수 나누기 및 나머지 결과를 모두 컴퓨팅합니다.

부동 소수점 나머지

floatdouble 피연산자의 경우 유한 xy에 대한 x % y의 결과는 다음과 같은 z 값입니다.

  • 0이 아닌 경우 z의 부호는 x의 부호와 동일합니다.
  • z의 절대 값은 |x| - n * |y|에서 생성된 값입니다. 여기서 n|x| / |y|보다 작거나 같은 가능한 최대 정수이고 |x||y|는 각각 xy의 절대 값입니다.

참고 항목

나머지 계산 방법은 정수 피연산자에 사용되는 것과 유사하지만 IEEE 754 사양과는 다릅니다. IEEE 754 사양을 준수하는 나머지 작업이 필요한 경우 Math.IEEERemainder 메서드를 사용합니다.

무한 피연산자가 있는 % 연산자의 동작에 대한 자세한 내용은 C# 언어 사양나머지 연산자 섹션을 참조하세요.

decimal 피연산자의 경우 나머지 연산자 %System.Decimal 형식의 나머지 연산자와 동일합니다.

다음 예제에서는 부동 소수점 피연산자를 포함한 나머지 연산자의 동작을 보여줍니다.

Console.WriteLine(-5.2f % 2.0f); // output: -1.2
Console.WriteLine(5.9 % 3.1);    // output: 2.8
Console.WriteLine(5.9m % 3.1m);  // output: 2.8

더하기 연산자 +

더하기 연산자 +는 피연산자의 합계를 계산합니다.

Console.WriteLine(5 + 4);       // output: 9
Console.WriteLine(5 + 4.3);     // output: 9.3
Console.WriteLine(5.1m + 4.2m); // output: 9.3

문자열 연결 및 대리자 조합의 경우 + 연산자를 사용할 수도 있습니다. 자세한 내용은 참조는 ++=연산자 문서를 참조하세요.

빼기 연산자 -

빼기 연산자 -는 왼쪽 피연산자에서 오른쪽 피연산자를 뺍니다.

Console.WriteLine(47 - 3);      // output: 44
Console.WriteLine(5 - 4.3);     // output: 0.7
Console.WriteLine(7.5m - 2.3m); // output: 5.2

대리자 제거를 위해 - 연산자를 사용할 수도 있습니다. 자세한 내용은 참조는 --=연산자 문서를 참조하세요.

복합 할당

이진 연산자(op)의 경우 양식의 복합 할당 식

x op= y

위의 식은 아래의 식과 동일합니다.

x = x op y

단, x가 한 번만 계산됩니다.

다음 예제에서는 산술 연산자를 사용하는 복합 할당의 사용법을 보여줍니다.

int a = 5;
a += 9;
Console.WriteLine(a);  // output: 14

a -= 4;
Console.WriteLine(a);  // output: 10

a *= 2;
Console.WriteLine(a);  // output: 20

a /= 4;
Console.WriteLine(a);  // output: 5

a %= 3;
Console.WriteLine(a);  // output: 2

숫자 승격으로 인해 op 연산의 결과가 암시적으로 xT 형식으로 변환되지 못할 수 있습니다. 이 경우 op가 미리 정의된 연산자이고 연산의 결과가 명시적으로 xT 형식으로 변환 가능하다면 x op= y 양식의 복합 할당 식이 x = (T)(x op y)에 해당합니다. 단 x는 한 번만 평가됩니다. 다음 예제에서는 해당 동작을 보여줍니다.

byte a = 200;
byte b = 100;

var c = a + b;
Console.WriteLine(c.GetType());  // output: System.Int32
Console.WriteLine(c);  // output: 300

a += b;
Console.WriteLine(a);  // output: 44

앞의 예에서 값 44는 값 300byte 형식으로 변환한 결과입니다.

참고 항목

확인된 오버플로 검사 컨텍스트에서 앞의 예는 OverflowException을 throw합니다. 자세한 내용은 정수 산술 오버플로 섹션을 참조하세요.

각각 +=-= 연산자를 사용하여 이벤트에서 구독하거나 구독을 취소할 수도 있습니다. 자세한 내용은 이벤트를 구독 및 구독 취소하는 방법을 참조하세요.

연산자 우선 순위 및 계산 방향

다음 목록에서는 산술 연산자를 가장 높은 우선 순위부터 가장 낮은 것으로 정렬합니다.

  • 후위 증가 x++ 및 감소 x-- 연산자
  • 전위 증가 ++x 및 감소 --x 및 단항 +- 연산자
  • 곱하기 *, /% 연산자
  • 가감 +- 연산자

이진 산술 연산자는 왼쪽 결합형입니다. 즉, 우선 순위 수준이 같은 연산자는 왼쪽에서 오른쪽으로 계산됩니다.

괄호(())를 사용하여 연산자 우선 순위와 연결에 따라 주어진 계산 순서를 변경할 수 있습니다.

Console.WriteLine(2 + 2 * 2);   // output: 6
Console.WriteLine((2 + 2) * 2); // output: 8

Console.WriteLine(9 / 5 / 2);   // output: 0
Console.WriteLine(9 / (5 / 2)); // output: 4

우선 순위 수준에 따라 정렬된 전체 연산자 목록은 C# 연산자 문서의 연산자 우선 순위 섹션을 참조하세요.

산술 오버플로 및 0으로 나누기

산술 연산의 결과가 관련된 숫자 형식의 가능한 유한 값 범위를 벗어나는 경우 산술 연산자의 동작은 해당하는 피연산자의 형식에 따라 달라집니다.

정수 산술 오버플로

정수를 0으로 나누면 항상 DivideByZeroException이 throw됩니다.

정수 산술 오버플로가 발생하면 선택 또는 선택 취소할 수 있는 오버플로 검사 컨텍스트가 결과 동작을 제어합니다.

  • checked 컨텍스트인 경우 상수 식에서 오버플로가 일어나면 컴파일 시간 오류가 발생합니다. 그렇지 않으면, 런타임 시 작업을 수행하는 경우 OverflowException이 throw됩니다.
  • unchecked 컨텍스트에서는 대상 형식에 맞지 않는 상위 비트를 버려서 해당 결과가 잘려집니다.

checked 및 unchecked 문과 함께 checkedunchecked 연산자를 사용하여 식을 계산하는 오버플로 검사 컨텍스트를 제어합니다.

int a = int.MaxValue;
int b = 3;

Console.WriteLine(unchecked(a + b));  // output: -2147483646
try
{
    int d = checked(a + b);
}
catch(OverflowException)
{
    Console.WriteLine($"Overflow occurred when adding {a} to {b}.");
}

기본적으로 산술 연산은 unchecked 컨텍스트에서 발생합니다.

부동 소수점 산술 오버플로

floatdouble 형식을 포함한 산술 연산은 예외를 throw하지 않습니다. 이러한 형식의 산술 연산 결과는 무한대를 나타내거나 숫자가 아닌 특수 값 중 하나일 수 있습니다.

double a = 1.0 / 0.0;
Console.WriteLine(a);                    // output: Infinity
Console.WriteLine(double.IsInfinity(a)); // output: True

Console.WriteLine(double.MaxValue + double.MaxValue); // output: Infinity

double b = 0.0 / 0.0;
Console.WriteLine(b);                // output: NaN
Console.WriteLine(double.IsNaN(b));  // output: True

decimal 형식의 피연산자의 경우 산술 오버플로는 항상 OverflowException을 throw합니다. 0으로 나누면 항상 DivideByZeroException이 throw됩니다.

반올림 오류

실수 및 부동 소수점 산술의 부동 소수점 표현을 일반적으로 제한함으로 인해 부동 소수점 형식을 사용하는 계산에서 반올림 오류가 발생할 수 있습니다. 즉, 생성된 식의 결과는 예상되는 수학적 결과와 다를 수 있습니다. 다음 예제에서는 이러한 몇몇 사례에 대해 설명합니다.

Console.WriteLine(.41f % .2f); // output: 0.00999999

double a = 0.1;
double b = 3 * a;
Console.WriteLine(b == 0.3);   // output: False
Console.WriteLine(b - 0.3);    // output: 5.55111512312578E-17

decimal c = 1 / 3.0m;
decimal d = 3 * c;
Console.WriteLine(d == 1.0m);  // output: False
Console.WriteLine(d);          // output: 0.9999999999999999999999999999

자세한 내용은 System.Double, System.Single 또는 System.Decimal 참조 페이지에서 설명을 참조하세요.

연산자 오버로드 가능성

사용자 정의 형식은 단항(++, --, +-) 및 이진(*, /, %, +-) 산술 연산자를 오버로드할 수 있습니다. 이항 연산자가 오버로드되면 해당하는 복합 대입 연산자도 암시적으로 오버로드됩니다. 사용자 정의 형식은 복합 대입 연산자를 명시적으로 오버로드할 수 없습니다.

사용자 정의 확인 연산자

C# 11부터 산술 연산자를 오버로드할 때 checked 키워드를 사용하여 해당 연산자의 확인된 버전을 정의할 수 있습니다. 다음 예제에서는 해당 작업을 수행하는 방법을 보여줍니다.

public record struct Point(int X, int Y)
{
    public static Point operator checked +(Point left, Point right)
    {
        checked
        {
            return new Point(left.X + right.X, left.Y + right.Y);
        }
    }
    
    public static Point operator +(Point left, Point right)
    {
        return new Point(left.X + right.X, left.Y + right.Y);
    }
}

확인된 연산자를 정의할 때 checked 한정자 없이 해당 연산자도 정의해야 합니다. 확인된 연산자는 확인된 컨텍스트에서 호출됩니다. checked 한정자가 없는 연산자는 확인되지 않은 컨텍스트에서 호출됩니다. checked 한정자 없이 연산자만 제공하면 checkedunchecked 컨텍스트 모두에서 호출됩니다.

두 버전의 연산자를 모두 정의하는 경우 다음과 같이 작업 결과가 너무 커서 결과 형식에 표시할 수 없는 경우에만 동작이 다를 것으로 예상됩니다.

  • 확인된 연산자는 OverflowException을 throw합니다.
  • checked 한정자가 없는 연산자는 잘린 결과를 나타내는 인스턴스를 반환합니다.

기본 제공된 산술 연산자의 동작 차이에 대한 자세한 내용은 산술 오버플로 및 0으로 나누기 섹션을 참조하세요.

다음 연산자 중 하나를 오버로드하는 경우에만 checked 한정자를 사용할 수 있습니다.

참고 항목

검사된 연산자 본문 내의 오버플로 검사 컨텍스트는 checked 한정자의 존재 여부에 영향을 받지 않습니다. 기본 컨텍스트는 CheckForOverflowUnderflow 컴파일러 옵션의 값으로 정의됩니다. 이 섹션의 시작 부분에 있는 예에서 볼 수 있듯이 checkedunchecked을 사용하여 오버플로 검사 컨텍스트를 명시적으로 지정합니다.

C# 언어 사양

자세한 내용은 C# 언어 사양의 다음 섹션을 참조하세요.

참고 항목