.NET 7은 기본 클래스 라이브러리에 새로운 수학 관련 제네릭 인터페이스를 도입했습니다. 이러한 인터페이스의 가용성은 제네릭 형식 또는 메서드의 형식 매개 변수를 "숫자와 유사한"으로 제한할 수 있습니다. 또한 C# 11 이상에서는 인터페이스 멤버를 정의static virtual
할 수 있습니다. 연산자를 로 static
선언해야 하므로 이 새로운 C# 기능을 사용하면 숫자와 유사한 형식에 대한 새 인터페이스에서 연산자를 선언할 수 있습니다.
이러한 혁신을 통해 일반적으로 수학 연산을 수행할 수 있습니다. 즉, 작업 중인 정확한 형식을 알 필요 없이 수행할 수 있습니다. 예를 들어 두 개의 숫자를 추가하는 메서드를 작성하려는 경우 이전에는 각 형식에 대한 메서드 오버로드(예: static int Add(int first, int second)
및 static float Add(float first, float second)
)를 추가해야 했습니다. 이제 형식 매개 변수가 숫자와 유사한 형식으로 제한되는 단일 제네릭 메서드를 작성할 수 있습니다. 다음은 그 예입니다.
static T Add<T>(T left, T right)
where T : INumber<T>
{
return left + right;
}
이 메서드에서 형식 매개 변수 T
는 새 INumber<TSelf> 인터페이스를 구현하는 형식으로 제한됩니다.
INumber<TSelf> 는 IAdditionOperators<TSelf,TOther,TResult>+ 연산자를 포함하는 인터페이스를 구현합니다. 이를 통해 메서드는 일반적으로 두 숫자를 추가할 수 있습니다. 메서드는 모든 .NET의 기본 제공 숫자 형식과 함께 사용할 수 있으며, 이는 모두 .NET 7에서 INumber<TSelf>를 구현하도록 업데이트되었기 때문입니다.
라이브러리 작성자는 "중복" 오버로드를 제거하여 코드 베이스를 간소화할 수 있으므로 제네릭 수학 인터페이스의 이점을 가장 활용할 수 있습니다. 다른 개발자는 사용하는 API가 더 많은 형식을 지원하기 시작할 수 있으므로 간접적으로 이점을 얻을 수 있습니다.
인터페이스
인터페이스는 사용자가 자신의 인터페이스를 정의할 수 있을 만큼 정밀하게 설계되었으며, 또한 사용하기에 쉽게 이해할 수 있게끔 세분화되었습니다. 이 정도까지 대부분의 사용자가 상호 작용하는 몇 가지 핵심 숫자 인터페이스(예: INumber<TSelf> 및 IBinaryInteger<TSelf>.)가 있습니다. 보다 세분화된 IAdditionOperators<TSelf,TOther,TResult> 및 ITrigonometricFunctions<TSelf>와 같은 인터페이스는 이러한 유형을 지원하고, 고유의 도메인별 숫자 인터페이스를 정의하는 개발자가 사용할 수 있습니다.
숫자 인터페이스
이 섹션에서는 숫자와 유사한 형식 및 사용할 수 있는 System.Numerics 기능을 설명하는 인터페이스에 대해 설명합니다.
인터페이스 이름 | 설명 |
---|---|
IBinaryFloatingPointIeee754<TSelf> | IEEE 754 표준을 구현하는 이진 부동 소수점 형식1 에 공통적인 API를 노출합니다. |
IBinaryInteger<TSelf> | 이진 정수2에 공통적인 API를 노출합니다. |
IBinaryNumber<TSelf> | 이진 번호에 공통적인 API를 노출합니다. |
IFloatingPoint<TSelf> | 부동 소수점 형식에 공통적인 API를 노출합니다. |
IFloatingPointIeee754<TSelf> | IEEE 754 표준을 구현하는 부동 소수점 형식에 공통적인 API를 노출합니다. |
INumber<TSelf> | 비교 가능한 숫자 형식(사실상 "실제" 숫자 도메인)에 공통적인 API를 노출합니다. |
INumberBase<TSelf> | 모든 숫자 형식(사실상 "복합" 숫자 도메인)에 공통적인 API를 노출합니다. |
ISignedNumber<TSelf> | 모든 부호 있는 숫자 유형(예: NegativeOne 개념)에 공통적인 API를 제공합니다. |
IUnsignedNumber<TSelf> | 서명되지 않은 모든 숫자 형식에 공통적인 API를 노출합니다. |
IAdditiveIdentity<TSelf,TResult> |
(x + T.AdditiveIdentity) == x 개념을 설명합니다. |
IMinMaxValue<TSelf> |
T.MinValue 및 T.MaxValue 의 개념을 드러냅니다. |
IMultiplicativeIdentity<TSelf,TResult> |
(x * T.MultiplicativeIdentity) == x 개념을 설명합니다. |
1이진 부동 소수점 형식은 Double(double
), Half, 및 Single(float
)입니다.
2이진 정수 타입은 Byte (byte
), Int16 (short
), Int32 (int
), Int64 (long
), Int128, IntPtr (nint
), SByte (sbyte
), UInt16 (ushort
), UInt32 (uint
), UInt64 (ulong
), UInt128, 및 UIntPtr (nuint
)입니다.
직접 사용할 가능성이 가장 큰 인터페이스는 INumber<TSelf>에 해당하는 인터페이스입니다. 형식이 이 인터페이스를 구현하는 경우 값에 기호가 있고( unsigned
양수로 간주되는 형식 포함) 동일한 형식의 다른 값과 비교할 수 있음을 의미합니다.
INumberBase<TSelf> 에서는 복잡한 숫자와 허수 등의 고급 개념(예: 음수의 제곱근)을 제공합니다. 모든 숫자 형식에 모든 연산이 적합한 것은 아니므로 같은 IFloatingPointIeee754<TSelf>다른 인터페이스가 생성되었습니다. 예를 들어 숫자의 바닥 계산은 부동 소수점 형식에만 적합합니다. .NET 기본 클래스 라이브러리에서 부동 소수점 형식 Double 은 IFloatingPointIeee754<TSelf> 구현하지만 Int32 구현하지 않습니다.
여러 인터페이스는 Char, DateOnly, DateTime, DateTimeOffset, Decimal, Guid, TimeOnly, 및 TimeSpan를 포함한 다양한 형식에 의해 구현됩니다.
다음 표에서는 각 인터페이스에서 노출하는 핵심 API 중 일부를 보여 줍니다.
인터페이스 | API 이름 | 설명 |
---|---|---|
IBinaryInteger<TSelf> | DivRem |
몫과 나머지를 동시에 계산합니다. |
LeadingZeroCount |
이진 표현에서 선행 0비트 수를 계산합니다. | |
PopCount |
이진 표현의 집합 비트 수를 계산합니다. | |
RotateLeft |
비트를 왼쪽으로 회전하는데, 이는 원형 왼쪽 시프트라고도 합니다. | |
RotateRight |
비트를 오른쪽으로 회전시키며, 이를 원형 우측 시프트라고도 합니다. | |
TrailingZeroCount |
이진 표현의 후행 0비트 수를 계산합니다. | |
IFloatingPoint<TSelf> | Ceiling |
값을 양수 무한대로 반올림합니다. +4.5는 +5가 되고 -4.5는 -4가 됩니다. |
Floor |
값을 음의 무한대로 반올림합니다. +4.5는 +4가 되고 -4.5는 -5가 됩니다. | |
Round |
지정된 반올림 모드를 사용하여 값을 반올림합니다. | |
Truncate |
값을 0으로 반올림합니다. +4.5는 +4가 되고 -4.5는 -4가 됩니다. | |
IFloatingPointIeee754<TSelf> | E |
형식에 대한 Euler의 번호를 나타내는 값을 가져옵니다. |
Epsilon |
형식에 대해 0보다 큰 가장 작은 표현 가능 값을 가져옵니다. | |
NaN |
형식을 나타내는 NaN 값을 가져옵니다. |
|
NegativeInfinity |
형식을 나타내는 -Infinity 값을 가져옵니다. |
|
NegativeZero |
형식을 나타내는 -Zero 값을 가져옵니다. |
|
Pi |
형식을 나타내는 Pi 값을 가져옵니다. |
|
PositiveInfinity |
형식을 나타내는 +Infinity 값을 가져옵니다. |
|
Tau |
형식을 나타내는 Tau 값(2 * Pi )을 가져옵니다. |
|
(기타) | (함수 인터페이스 아래에 나열된 전체 인터페이스 집합을 구현합니다.) | |
INumber<TSelf> | Clamp |
값을 지정된 최소값 및 최대값보다 작지 않은 값으로 제한합니다. |
CopySign |
지정된 값의 부호를 지정된 다른 값과 동일하게 설정합니다. | |
Max |
두 값 중 더 큰 값을 반환하고 NaN 입력이 두 값 중 하나일 경우 반환합니다 NaN . |
|
MaxNumber |
두 값 중 더 큰 값을 반환하고 입력이 1 NaN 개인 경우 숫자를 반환합니다. |
|
Min |
두 값 중 더 작은 값을 반환하고 입력 중 하나가 NaN 이면 반환합니다 NaN . |
|
MinNumber |
두 값 중 더 작은 값을 반환하고 입력 NaN 이 1개인 경우 숫자를 반환합니다. |
|
Sign |
음수 값에 대한 -1, 0의 경우 0, 양수 값의 경우 +1을 반환합니다. | |
INumberBase<TSelf> | One |
형식의 값 1을 가져옵니다. |
Radix |
형식의 radix 또는 base를 가져옵니다. Int32 는 2를 반환합니다. Decimal 10을 반환합니다. | |
Zero |
형식의 값 0을 가져옵니다. | |
CreateChecked |
입력이 맞지 않을 경우 OverflowException을(를) 던져 값을 생성합니다.1 | |
CreateSaturating |
입력이 맞지 않을 경우 T.MinValue 또는 T.MaxValue 로 고정하여 값을 만듭니다.1 |
|
CreateTruncating |
입력이 맞지 않는 경우 래핑하여 다른 값에서 값을 만듭니다. 1 | |
IsComplexNumber |
값에 0이 아닌 실제 부분과 0이 아닌 허수 부분이 있으면 true를 반환합니다. | |
IsEvenInteger |
값이 짝수이면 true를 반환합니다. 2.0은 true 을 반환하고, 2.2는 false 을 반환합니다. |
|
IsFinite |
값이 무한이 아닌 NaN 경우 true를 반환합니다. |
|
IsImaginaryNumber |
값에 실제 부분이 0이면 true를 반환합니다. 즉 0 , 허수이고 1 + 1i 그렇지 않습니다. |
|
IsInfinity |
값이 무한대를 나타내는 경우 true를 반환합니다. | |
IsInteger |
값이 정수이면 true를 반환합니다. 2.0 및 3.0 반환 true 및 2.2 및 3.1 반환 false . |
|
IsNaN |
값이 NaN 을 나타내면 true를 반환합니다. |
|
IsNegative |
값이 음수이면 true를 반환합니다. 여기에는 -0.0이 포함됩니다. | |
IsPositive |
값이 양수이면 true를 반환합니다. 여기에는 0 및 +0.0이 포함됩니다. | |
IsRealNumber |
값에 허수 부분이 0이면 true를 반환합니다. 즉, 0은 모든 INumber<T> 형식과 마찬가지로 실제입니다. |
|
IsZero |
값이 0을 나타내는 경우 true를 반환합니다. 여기에는 0, +0.0 및 -0.0이 포함됩니다. | |
MaxMagnitude |
절대값의 크기를 비교하여 더 큰 값을 반환하며, 만약 어느 한 입력이 NaN 라면 NaN 을 반환합니다. |
|
MaxMagnitudeNumber |
절대값이 더 큰 값을 반환하고 입력이 NaN 1인 경우 숫자를 반환합니다. |
|
MinMagnitude |
입력 값 중 하나가 NaN 일 경우 NaN 을 반환하며, 그렇지 않으면 절대값이 더 작은 값을 반환합니다. |
|
MinMagnitudeNumber |
절대값이 더 작은 값을 반환하고 입력 NaN 이 1인 경우 숫자를 반환합니다. |
|
ISignedNumber<TSelf> | NegativeOne |
형식에 대한 -1 값을 가져옵니다. |
1세 Create*
가지 메서드의 동작을 이해하려면 다음 예제를 고려하세요.
너무 큰 값이 지정된 경우의 예:
-
byte.CreateChecked(384)
이(가) OverflowException을(를) 발생시킵니다. -
byte.CreateSaturating(384)
는 384가 255보다 Byte.MaxValue 크므로 255를 반환합니다. -
byte.CreateTruncating(384)
는 가장 낮은 8비트를 사용하므로 128을 반환합니다(384에는 16진수 표현0x0180
이 있고 가장 낮은 8비트는0x80
128).
너무 작은 값이 지정된 경우의 예:
-
byte.CreateChecked(-384)
이(가) OverflowException을(를) 발생시킵니다. -
byte.CreateSaturating(-384)
는 -384 (0)보다 Byte.MinValue 작기 때문에 0을 반환합니다. -
byte.CreateTruncating(-384)
는 가장 낮은 8비트를 사용하므로 128을 반환합니다(384에는 16진수 표현0xFE80
이 있고 가장 낮은 8비트는0x80
128).
또한 Create*
메서드는 float
및 double
와 같은 IEEE 754 부동 소수점 형식에 대해 PositiveInfinity
, NegativeInfinity
, NaN
등의 특수 값을 사용할 때 몇 가지 특별한 고려 사항이 있습니다. 모든 세 개의 Create*
API는 CreateSaturating
로 동작합니다. 또한 MinValue
및 MaxValue
는 가장 큰 음수/양수 "표준" 숫자를 나타내지만, 실제 최소값과 최대값은 NegativeInfinity
및 PositiveInfinity
이므로, 대신 이 값으로 고정됩니다.
연산자 인터페이스
연산자 인터페이스는 C# 언어에서 사용할 수 있는 다양한 연산자에 해당합니다.
- 모든 형식에 대해 올바르지 않으므로 곱하기 및 나누기와 같은 작업을 명시적으로 페어링하지 않습니다. 예를 들어
Matrix4x4 * Matrix4x4
유효하지만Matrix4x4 / Matrix4x4
유효하지는 않습니다. - 일반적으로 입력 및 결과 형식은 두 정수로 나누어 정
double
3 / 2 = 1.5
수 집합의 평균을 계산하는 등의 시나리오를 지원하기 위해 다를 수 있습니다.
인터페이스 이름 | 정의된 연산자 |
---|---|
IAdditionOperators<TSelf,TOther,TResult> | x + y |
IBitwiseOperators<TSelf,TOther,TResult> |
x & y , 'x | y', x ^ y 및 ~x |
IComparisonOperators<TSelf,TOther,TResult> |
x < y , x > y , x <= y 및 x >= y |
IDecrementOperators<TSelf> |
--x 및 x-- |
IDivisionOperators<TSelf,TOther,TResult> | x / y |
IEqualityOperators<TSelf,TOther,TResult> |
x == y 및 x != y |
IIncrementOperators<TSelf> |
++x 및 x++ |
IModulusOperators<TSelf,TOther,TResult> | x % y |
IMultiplyOperators<TSelf,TOther,TResult> | x * y |
IShiftOperators<TSelf,TOther,TResult> |
x << y 및 x >> y |
ISubtractionOperators<TSelf,TOther,TResult> | x - y |
IUnaryNegationOperators<TSelf,TResult> | -x |
IUnaryPlusOperators<TSelf,TResult> | +x |
비고
일부 인터페이스는 선택되지 않은 일반 연산자 외에 확인된 연산자를 정의합니다. 확인된 연산자는 확인된 컨텍스트에서 호출되며 사용자 정의 형식이 오버플로 동작을 정의할 수 있도록 허용합니다. 예를 들어 CheckedSubtraction(TSelf, TOther)확인된 연산자를 구현하는 경우 예를 들어 Subtraction(TSelf, TOther)선택되지 않은 연산자도 구현해야 합니다.
함수 인터페이스
함수 인터페이스는 특정 숫자 인터페이스보다 더 광범위하게 적용되는 일반적인 수학 API를 정의합니다. 이러한 인터페이스는 모두 에 의해 IFloatingPointIeee754<TSelf>구현되며 나중에 다른 관련 형식에 의해 구현될 수 있습니다.
인터페이스 이름 | 설명 |
---|---|
IExponentialFunctions<TSelf> |
e^x , e^x - 1 , 2^x , 2^x - 1 , 10^x , 및 10^x - 1 를 지원하는 지수 함수를 제공합니다. |
IHyperbolicFunctions<TSelf> |
acosh(x) , asinh(x) , atanh(x) , cosh(x) , sinh(x) , 및 tanh(x) 를 지원하는 하이퍼볼릭 함수를 노출합니다. |
ILogarithmicFunctions<TSelf> |
ln(x) , ln(x + 1) , log2(x) , log2(x + 1) , log10(x) 및 log10(x + 1) 를 지원하는 로그 함수를 제공합니다. |
IPowerFunctions<TSelf> | 를 지원하는 전원 함수를 노출합니다 x^y . |
IRootFunctions<TSelf> | 루트 기능을 노출하여 cbrt(x) 및 sqrt(x) 를 지원합니다. |
ITrigonometricFunctions<TSelf> |
acos(x) , asin(x) , atan(x) , cos(x) , sin(x) , 및 tan(x) 를 지원하는 삼각 함수를 제공합니다. |
인터페이스 구문 분석 및 서식 지정
구문 분석 및 서식 지정은 프로그래밍의 핵심 개념입니다. 사용자 입력을 지정된 형식으로 변환하거나 사용자에게 형식을 표시할 때 일반적으로 사용됩니다. 이러한 인터페이스는 네임스페이스에 System 있습니다.
인터페이스 이름 | 설명 |
---|---|
IParsable<TSelf> |
T.Parse(string, IFormatProvider) 및 T.TryParse(string, IFormatProvider, out TSelf) 에 대한 지원을 제공합니다. |
ISpanParsable<TSelf> |
T.Parse(ReadOnlySpan<char>, IFormatProvider) 및 T.TryParse(ReadOnlySpan<char>, IFormatProvider, out TSelf) 에 대한 지원을 제공합니다. |
IFormattable 1 | 에 대한 value.ToString(string, IFormatProvider) 지원을 노출합니다. |
ISpanFormattable 1 | 에 대한 value.TryFormat(Span<char>, out int, ReadOnlySpan<char>, IFormatProvider) 지원을 노출합니다. |
1이 인터페이스는 새로운 인터페이스가 아니며 제네릭도 아닙니다. 그러나 모든 숫자 형식에 의해 구현되며 역 연산 IParsable
을 나타냅니다.
예를 들어 다음 프로그램은 형식 매개 변수가 제한 IParsable<TSelf>되는 제네릭 메서드를 사용하여 콘솔에서 읽는 두 숫자를 입력으로 사용합니다. 입력 및 결과 값의 형식 매개 변수가 제한 INumber<TSelf>되는 제네릭 메서드를 사용하여 평균을 계산한 다음 결과를 콘솔에 표시합니다.
using System.Globalization;
using System.Numerics;
static TResult Average<T, TResult>(T first, T second)
where T : INumber<T>
where TResult : INumber<TResult>
{
return TResult.CreateChecked( (first + second) / T.CreateChecked(2) );
}
static T ParseInvariant<T>(string s)
where T : IParsable<T>
{
return T.Parse(s, CultureInfo.InvariantCulture);
}
Console.Write("First number: ");
var left = ParseInvariant<float>(Console.ReadLine());
Console.Write("Second number: ");
var right = ParseInvariant<float>(Console.ReadLine());
Console.WriteLine($"Result: {Average<float, float>(left, right)}");
/* This code displays output similar to:
First number: 5.0
Second number: 6
Result: 5.5
*/
참고하십시오
.NET