本文内.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 left, T right)
where T : INumber
{
return left + right;
}
在此方法中,类型参数 T
约束为了实现新 INumber
库作者将从泛型数学接口中受益最多,因为他们可以通过删除“冗余”重载来简化其代码库。 其他开发人员将间接受益,因为他们使用的 API 可能会开始支持更多类型。
接口设计为既需要足够细化(以便用户可以在上面定义自己的接口),又要足够精细(以便易于使用)。 在这种情况下,大多数用户会与一些核心数字接口进行交互,例如 INumber
本部分介绍 System.Numerics 中的接口,这些接口描述了类似于数字的类型及其可用的功能。
接口名称 | 说明 |
---|---|
IBinaryFloatingPointIeee754 |
公开对实现 IEEE 754 标准的二进制浮点类型1通用的 API。 |
IBinaryInteger |
公开对二进制整数通用的 API2。 |
IBinaryNumber |
公开对二进制数字通用的 API。 |
IFloatingPoint |
公开对浮点类型通用的 API。 |
IFloatingPointIeee754 |
公开对实现 IEEE 754 标准的浮点类型通用的 API。 |
INumber |
公开对可比较数字类型(实际上是“实数”数字域)通用的 API。 |
INumberBase |
公开对所有数字类型(实际上是“复数”数字域)通用的 API。 |
ISignedNumber |
公开对所有有符号数字类型通用的 API(例如 NegativeOne 的概念)。 |
IUnsignedNumber |
公开对所有无符号数字类型通用的 API。 |
IAdditiveIdentity |
公开 (x + T.AdditiveIdentity) == x 的概念。 |
IMinMaxValue |
公开 T.MinValue 和 T.MaxValue 的概念。 |
IMultiplicativeIdentity |
公开 (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
)。
最有可能直接使用的接口是 INumberunsigned
类型,这些类型被认为是正数)并且可以与相同类型的其他值进行比较。 INumberBase
一些接口也由各种其他类型实现,包括 Char、DateOnly、DateTime、DateTimeOffset、Decimal、Guid、TimeOnly 和 TimeSpan。
下表显示了每个接口公开的一些核心 API。
接口 | API 名称 | 说明 |
---|---|---|
IBinaryInteger |
DivRem |
同时计算商和余数。 |
LeadingZeroCount |
计算二进制表示中的前导零位数。 | |
PopCount |
计算二进制表示中的设置位数。 | |
RotateLeft |
向左旋转位,有时也称为循环左移。 | |
RotateRight |
向右旋转位,有时也称为循环右移。 | |
TrailingZeroCount |
计算二进制表示中的尾随零位数。 | |
IFloatingPoint |
Ceiling |
将值向正无穷方向舍入。 +4.5 变为 +5,-4.5 变为 -4。 |
Floor |
将值向负无穷方向舍入。 +4.5 变为 +4,-4.5 变为 -5。 | |
Round |
使用指定的舍入模式对值进行舍入。 | |
Truncate |
将值向零舍入。 +4.5 变为 +4,-4.5 变为 -4。 | |
IFloatingPointIeee754 |
E |
获取一个值,该值表示该类型的欧拉数。 |
Epsilon |
获取该类型的大于零的最小可表示值。 | |
NaN |
获取表示类型 NaN 的值。 |
|
NegativeInfinity |
获取表示类型 -Infinity 的值。 |
|
NegativeZero |
获取表示类型 -Zero 的值。 |
|
Pi |
获取表示类型 Pi 的值。 |
|
PositiveInfinity |
获取表示类型 +Infinity 的值。 |
|
Tau |
获取表示类型 Tau (2 * Pi ) 的值。 |
|
(其他) | (实现函数接口下列出的全部接口。) | |
INumber |
Clamp |
将值限制为不大于也不小于指定的最小值和最大值。 |
CopySign |
将指定值的符号设置为与另一个指定值相同。 | |
Max |
返回两个值中的较大值,如果任一输入为 NaN ,则返回 NaN 。 |
|
MaxNumber |
返回两个值中的较大值,如果一个输入为 NaN ,则返回数字。 |
|
Min |
返回两个值中的较小值,如果任一输入为 NaN ,则返回 NaN 。 |
|
MinNumber |
返回两个值中的较小值,如果一个输入为 NaN ,则返回数字。 |
|
Sign |
返回 -1 表示负值,0 表示零,+1 表示正值。 | |
INumberBase |
One |
获取类型的值 1。 |
Radix |
获取类型的基数。 Int32 返回 2。 Decimal 返回 10。 | |
Zero |
获取类型的值 0。 | |
CreateChecked |
创建一个值,如果输入不合适,则引发 OverflowException。1 | |
CreateSaturating |
创建一个值,如果输入不合适,则钳制为 T.MinValue 或 T.MaxValue 。1 |
|
CreateTruncating |
从一个值创建另一个值,如果输入不适合,则环绕处理。1 | |
IsComplexNumber |
如果值具有非零实部和非零虚部,则返回 true。 | |
IsEvenInteger |
如果值为偶数整数,则返回 true。 2.0 返回 true ,2.2 返回 false 。 |
|
IsFinite |
如果值不是无限值且不是 NaN ,则返回 true。 |
|
IsImaginaryNumber |
如果值的实部为零,则返回 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 |
如果值的虚部为零,则返回 true。 这意味着 0 是实数,所有 INumber 类型也是如此。 |
|
IsZero |
如果值表示零,则返回 true。 这包括 0、+0.0 和 -0.0。 | |
MaxMagnitude |
返回绝对值较大的值,如果任一输入为 NaN ,则返回 NaN 。 |
|
MaxMagnitudeNumber |
返回绝对值较小的值,如果一个输入为 NaN ,则返回数字。 |
|
MinMagnitude |
返回绝对值较小的值,如果任一输入为 NaN ,则返回 NaN 。 |
|
MinMagnitudeNumber |
返回绝对值较小的值,如果一个输入为 NaN ,则返回数字。 |
|
ISignedNumber |
NegativeOne |
获取类型的值 -1。 |
1为帮助理解三种 Create*
方法的行为,请考虑以下示例。
给定值过大时的示例:
byte.CreateChecked(384)
将引发 OverflowException。byte.CreateSaturating(384)
返回 255,因为 384 大于 Byte.MaxValue(即 255)。byte.CreateTruncating(384)
返回 128,因为采用最低 8 位(384 的十六进制表示为 0x0180
,最低 8 位为 0x80
,即 128)。给定值过小时的示例:
byte.CreateChecked(-384)
将引发 OverflowException。byte.CreateSaturating(-384)
返回 0,因为 -384 小于 Byte.MinValue(即 0)。byte.CreateTruncating(-384)
返回 128,因为采用最低 8 位(384 的十六进制表示为 0xFE80
,最低 8 位为 0x80
,即 128)。Create*
方法对 IEEE 754 浮点类型也有一些特殊考虑,例如 float
和 double
,因为它们具有特殊值 PositiveInfinity
、NegativeInfinity
和 NaN
。 所有三个 Create*
API 都表现为 CreateSaturating
。 此外,虽然 MinValue
和 MaxValue
表示最大的负/正“正常”数,但实际的最小值和最大值是 NegativeInfinity
和 PositiveInfinity
,因此它们改为钳制这些值。
运算符接口对应于可用于 C# 语言的各种运算符。
Matrix4x4 * Matrix4x4
有效,但 Matrix4x4 / Matrix4x4
无效。double
(例如 3 / 2 = 1.5
)或计算一组整数的平均值等方案。接口名称 | 定义的运算符 |
---|---|
IAdditionOperators |
x + y |
IBitwiseOperators |
x & y 、x | y 、x ^ y 和 ~x |
IComparisonOperators |
x < y 、x > y 、x <= y 和 x >= y |
IDecrementOperators |
--x 和 x-- |
IDivisionOperators |
x / y |
IEqualityOperators |
x == y 和 x != y |
IIncrementOperators |
++x 和 x++ |
IModulusOperators |
x % y |
IMultiplyOperators |
x * y |
IShiftOperators |
x << y 和 x >> y |
ISubtractionOperators |
x - y |
IUnaryNegationOperators |
-x |
IUnaryPlusOperators |
+x |
备注
除了常规的 unchecked 运算符之外,一些接口还定义了 checked 运算符。 Checked 运算符在 checked 上下文中调用,并允许用户定义的类型定义溢出行为。 如果实现了 checked 运算符,例如 CheckedSubtraction(TSelf, TOther),则还必须实现 unchecked 的运算符,例如 Subtraction(TSelf, TOther)。
函数接口定义了比特定数值接口更广泛应用的泛型数学 API。 这些接口都由 IFloatingPointIeee754
接口名称 | 说明 |
---|---|
IExponentialFunctions |
公开支持 e^x 、e^x - 1 、2^x 、2^x - 1 、10^x 和 10^x - 1 的指数函数。 |
IHyperbolicFunctions |
公开支持 acosh(x) 、asinh(x) 、atanh(x) 、cosh(x) 、sinh(x) 和 tanh(x) 的双曲线函数。 |
ILogarithmicFunctions |
公开支持 ln(x) 、ln(x + 1) 、log2(x) 、log2(x + 1) 、log10(x) 和 log10(x + 1) 的对数函数。 |
IPowerFunctions |
公开支持 x^y 的幂函数。 |
IRootFunctions |
公开支持 cbrt(x) 和 sqrt(x) 的根函数。 |
ITrigonometricFunctions |
公开支持 acos(x) 、asin(x) 、atan(x) 、cos(x) 、sin(x) 和 tan(x) 的三角函数。 |
解析和格式化是编程中的核心概念。 它们通常在将用户输入转换为给定类型或向用户显示类型时使用。 这些接口位于 System 命名空间中。
接口名称 | 说明 |
---|---|
IParsable |
公开对 T.Parse(string, IFormatProvider) 和 T.TryParse(string, IFormatProvider, out TSelf) 的支持。 |
ISpanParsable |
公开对 T.Parse(ReadOnlySpan 和 T.TryParse(ReadOnlySpan 的支持。 |
IFormattable1 | 公开对 value.ToString(string, IFormatProvider) 的支持。 |
ISpanFormattable1 | 公开对 value.TryFormat(Span 的支持。 |
1此接口不是新接口,也不是泛型接口。 但是,它由所有数字类型实现,表示 IParsable
的逆运算。
例如,以下程序将两个数字作为输入,使用类型参数限制为 IParsable