Megosztás:


Általános matematika

A .NET 7 új, matematikai vonatkozású általános felületeket vezet be az alaposztály-kódtárba. Ezeknek az interfészeknek a rendelkezésre állása azt jelenti, hogy egy általános típus vagy metódus típusparaméterét "számszerű" értékre korlátozhatja. Emellett a C# 11-et és újabb verziót is használhatja a felülettagok definiálásáhozstatic virtual. Mivel az operátorokat static-ként kell deklarálni, ez az új C#-funkció lehetővé teszi, hogy az operátorok a számszerű típusok új felületeiben deklarálhatók legyenek.

Ezek az újítások együttesen lehetővé teszik a matematikai műveletek általános végrehajtását, vagyis anélkül, hogy pontosan ismernie kellene a használni kívánt típust. Ha például olyan metódust szeretne írni, amely két számot ad hozzá, korábban minden típushoz (például static int Add(int first, int second) és static float Add(float first, float second)) hozzá kellett adnia a metódus túlterhelését. Most már írhat egyetlen általános metódust, amelyben a típusparaméter számszerű típusra van korlátozva. Például:

static T Add<T>(T left, T right)
    where T : INumber<T>
{
    return left + right;
}

Ebben a metódusban a típusparaméter T az új INumber<TSelf> felületet megvalósító típusra van korlátozva. INumber<TSelf> implementálja az interfészt IAdditionOperators<TSelf,TOther,TResult> , amely a + operátort tartalmazza. Ez lehetővé teszi, hogy a metódus általánosan adja hozzá a két számot. A metódus használható a .NET beépített numerikus típusainak bármelyikével, mert mind frissítve lettek a INumber<TSelf> implementálásához a .NET 7-ben.

A kódtár-szerzők leginkább az általános matematikai felületek előnyeit élvezhetik, mivel a "redundáns" túlterhelések eltávolításával egyszerűsíthetik a kódbázisukat. Más fejlesztők közvetetten is profitálhatnak, mivel az általuk használt API-k több típust is támogathatnak.

Az interfészek

Az interfészek úgy lettek kialakítva, hogy elég részletesek legyenek ahhoz, hogy a felhasználók meg tudják határozni a saját felületeiket a tetején, miközben elég részletesek ahhoz, hogy könnyen felhasználhatók legyenek. Ilyen mértékben van néhány alapvető numerikus felület, amellyel a felhasználók többsége interakcióba lép, például INumber<TSelf> és IBinaryInteger<TSelf>. A részletesebb interfészek, például IAdditionOperators<TSelf,TOther,TResult> és ITrigonometricFunctions<TSelf>, támogatják ezeket a típusokat, és a saját tartományspecifikus numerikus felületeiket definiáló fejlesztők számára érhetők el.

Numerikus felületek

Ez a szakasz az System.Numerics felületeket ismerteti, amelyek a szám-szerű típusokat és a számukra elérhető funkciókat írják le.

Interfész neve Leírás
IBinaryFloatingPointIeee754<TSelf> Az IEEE 754 szabványt implementáló bináris lebegőpontos típusok általános API-jait teszi elérhetővé.
IBinaryInteger<TSelf> A2. bináris egész számokhoz gyakran használt API-kat teszi elérhetővé.
IBinaryNumber<TSelf> A bináris számokhoz gyakran használt API-kat tesz elérhetővé.
IFloatingPoint<TSelf> A lebegőpontos típusok gyakran használt API-jait teszi elérhetővé.
IFloatingPointIeee754<TSelf> Az IEEE 754 szabványt megvalósító lebegőpontos típusok számára gyakran használt API-kat tesz elérhetővé.
INumber<TSelf> Hasonló számtípusokhoz (gyakorlatilag a "valós" számtartományhoz) hasonló API-kat tesz elérhetővé.
INumberBase<TSelf> Az összes számtípushoz (gyakorlatilag az "összetett" számtartományhoz) tartozó API-kat teszi elérhetővé.
ISignedNumber<TSelf> Az összes aláírt számtípushoz (például a NegativeOnefogalomhoz) tartozó API-kat teszi elérhetővé.
IUnsignedNumber<TSelf> Az összes nem aláírt számtípushoz gyakran használt API-kat tesz elérhetővé.
IAdditiveIdentity<TSelf,TResult> A fogalmat (x + T.AdditiveIdentity) == xteszi elérhetővé.
IMinMaxValue<TSelf> Bemutatja a(z) T.MinValue és T.MaxValue koncepcióját.
IMultiplicativeIdentity<TSelf,TResult> A fogalmat (x * T.MultiplicativeIdentity) == xteszi elérhetővé.

1A bináris lebegőpontos típusok a következők Double : (double), Halfés Single (float).

2A bináris egész számtípusok a következők: Byte (byte), Int16 (short), Int32 (int), Int64 (long), Int128, IntPtr (nint), SByte (sbyte), UInt16 (ushort), UInt32 (uint), UInt64 (ulong), UInt128, és UIntPtr (nuint).

A közvetlenül használt felület valószínűleg a INumber<TSelf>, amely nagyjából egy valós számnak felel meg. Ha egy típus implementálja ezt az interfészt, az azt jelenti, hogy egy értéknek van jele (ide tartoznak unsigned a pozitívnak tekintett típusok), és összehasonlítható az azonos típusú más értékekkel. INumberBase<TSelf> összetettebb fogalmakat, például összetett és képzeletbeli számokat biztosít, például egy negatív szám négyzetgyökét. Más interfészek, például IFloatingPointIeee754<TSelf>azért lettek létrehozva, mert nem minden műveletnek van értelme minden számtípushoz – például egy szám padlójának kiszámítása csak lebegőpontos típusok esetében van értelme. A .NET alaposztálytárban a lebegőpontos típus Double implementálódik IFloatingPointIeee754<TSelf> , de Int32 nem.

Számos interfészt más típusok is implementálnak, például Char, , DateOnlyDateTime, DateTimeOffset, Decimal, Guid, TimeOnlyés TimeSpan.

Az alábbi táblázat az egyes felületek által közzétett alapvető API-kat mutatja be.

Interfész API név Leírás
IBinaryInteger<TSelf> DivRem A hányadost és a maradékot egyszerre számítja ki.
LeadingZeroCount Megszámolja az első nulla bitek számát a bináris ábrázolásban.
PopCount Megszámolja a bináris reprezentációban lévő beállított bitek számát.
RotateLeft Balra elforgatja a biteket, más néven körkörös bal eltolás.
RotateRight Jobbra elforgatja a biteket, más néven körkörös jobbra váltást.
TrailingZeroCount Megszámolja a záró nulla bitek számát a bináris ábrázolásban.
IFloatingPoint<TSelf> Ceiling Az értéket a pozitív végtelen felé kerekiti. A +4.5 +5, a -4.5 pedig -4 lesz.
Floor Az értéket negatív végtelen felé kerekíti. A +4.5 +4, a -4.5 pedig -5 lesz.
Round A megadott kerekítési mód alkalmazásával kerekíti az értéket.
Truncate Az értéket a nulla irányába kerekíti. A +4.5 +4, a -4.5 pedig -4 lesz.
IFloatingPointIeee754<TSelf> E A típus Euler-számát jelölő értéket kap.
Epsilon A legkisebb, nullánál nagyobb reprezentálható értéket adja meg a típushoz.
NaN Lekéri a típushoz tartozó NaN értéket.
NegativeInfinity Lekéri a típushoz tartozó -Infinity értéket.
NegativeZero Lekéri a típushoz tartozó -Zero értéket.
Pi Lekéri a típushoz tartozó Pi értéket.
PositiveInfinity Lekéri a típushoz tartozó +Infinity értéket.
Tau Lekéri a Tau értékét, amely a 2 * Pi típushoz tartozik.
(Egyéb) (Implementálja a függvényillesztők alatt felsorolt interfészek teljes készletét.)
INumber<TSelf> Clamp A megadott minimális és maximális értéknél nem kisebb értékre korlátozza az értéket.
CopySign Egy megadott érték előjelét egy másik megadott értékkel megegyezőre állítja.
Max Két érték közül a nagyobbat adja vissza, és NaN-t ad vissza, ha bármelyik bemenet NaN.
MaxNumber Két érték közül a nagyobbat adja eredményül; ha az egyik bemenet a NaN, akkor ezt a számot adja vissza.
Min Két érték közül a kisebbet adja eredményül, hacsak egyik bemenet sem egyenlő NaN; különben NaN-t adja vissza.
MinNumber Két érték közül a kisebbet adja eredményül. Ha egy bemenet van NaN, akkor a számot adja vissza.
Sign Negatív értékeknél -1, nullánál 0, pozitív értékeknél pedig +1 értéket ad vissza.
INumberBase<TSelf> One Megkapja a típus értékét, amely 1.
Radix Lekéri a típus radixát vagy bázist. Int32 visszaadja a 2 értéket. Decimal 10-et ad vissza.
Zero Lekéri a típus 0 értékét.
CreateChecked Értéket hoz létre, és OverflowException kivételt dob, ha a bemenet nem fér el.1
CreateSaturating Értéket hoz létre, amely T.MinValue vagy T.MaxValue közé van szorítva, ha a bemenet nem fér el.1
CreateTruncating Létrehoz egy értéket egy másik értékből, körbefuttatva, ha a bemenet nem fér el. 1
IsComplexNumber Igaz értéket ad vissza, ha az érték nem nulla valós és nem nulla képzetes részből áll.
IsEvenInteger Igaz értéket ad vissza, ha az érték páros egész szám. A 2.0 true-t ad vissza, és a 2.2 false-t ad vissza.
IsFinite Igaz értéket ad vissza, ha az érték nem végtelen és nem NaN.
IsImaginaryNumber Igaz értéket ad vissza, ha az érték nulla valós részből áll. Ez azt jelenti, hogy a 0 képzelt, és a 1 + 1i nem az.
IsInfinity Igaz értéket ad vissza, ha az érték a végtelent jelöli.
IsInteger Igaz értéket ad vissza, ha az érték egész szám. A 2.0 és a 3.0 visszaadja a true, míg a 2.2 és a 3.1 visszaadja a false.
IsNaN Igaz értéket ad vissza, ha az érték az értéket jelöli NaN.
IsNegative Igaz értéket ad vissza, ha az érték negatív. Ide tartozik a -0.0.
IsPositive Igaz értéket ad vissza, ha az érték pozitív. Ide tartozik a 0 és a +0.0.
IsRealNumber Igaz értéket ad vissza, ha az értéknek nulla képzelt része van. Ez azt jelenti, hogy a 0 valós, mint minden INumber<T> típus.
IsZero Igaz értéket ad vissza, ha az érték nulla. Ebbe beletartozik a 0, a +0,0 és a -0,0.
MaxMagnitude A nagyobb abszolút értékkel rendelkező értéket adja eredményül, NaN értéket adva vissza, ha bármelyik bemenet NaN.
MaxMagnitudeNumber A nagyobb abszolút értékkel rendelkező értéket adja eredményül, és a számot adja vissza, ha egy bemenet van NaN.
MinMagnitude Ha bármelyik bemenet NaN, akkor az érték NaN-at adja vissza, amelyiknek kisebb az abszolút értéke.
MinMagnitudeNumber Kisebb abszolút értékkel adja vissza az értéket, és a számot adja vissza, ha egy bemenet van NaN.
ISignedNumber<TSelf> NegativeOne Az értéket -1 kapja a típushoz.

1A három Create* módszer viselkedésének megértéséhez vegye figyelembe az alábbi példákat.

Példa túl nagy érték megadása esetén:

  • byte.CreateChecked(384) fog dobni egy OverflowException.
  • byte.CreateSaturating(384) 255 értéket ad vissza, mert a 384 nagyobb, mint Byte.MaxValue (ami 255).
  • byte.CreateTruncating(384) 128-at ad vissza, mert a legalacsonyabb 8 bitet veszi fel (a 384-nek a hexa-ábrázolása 0x0180van, a legalacsonyabb 8 bit pedig 0x80128).

Példa, ha túl kicsi értéket ad meg:

  • byte.CreateChecked(-384) fog dobni egy OverflowException.
  • byte.CreateSaturating(-384) 0 értéket ad vissza, mert -384 kisebb, mint Byte.MinValue (ami 0).
  • byte.CreateTruncating(-384) 128-at ad vissza, mert a legalacsonyabb 8 bitet veszi fel (a 384-nek a hexa-ábrázolása 0xFE80van, a legalacsonyabb 8 bit pedig 0x80128).

A Create* metódusok különleges szempontokat is figyelembe vesznek az IEEE 754 lebegőpontos típusok esetében, például float és double, mivel speciális értékekkel PositiveInfinityrendelkeznek , NegativeInfinityés NaN. Create* Mindhárom API úgy viselkedik, mint CreateSaturating. Bár a MinValue és MaxValue a legnagyobb negatív/pozitív "normál" számot képviselik, a tényleges minimum- és maximumértékek a NegativeInfinity, PositiveInfinity, így inkább ezekhez az értékekhez szorítják őket.

Kezelőfelületek

Az operátori felületek megfelelnek a C# nyelvhez elérhető különböző operátoroknak.

  • Kifejezetten nem párosítanak olyan műveleteket, mint a szorzás és az osztás, mivel ez nem minden típusra igaz. Például érvényes, Matrix4x4 * Matrix4x4 de Matrix4x4 / Matrix4x4 nem érvényes.
  • Általában lehetővé teszik, hogy a bemeneti és az eredménytípusok különbözzenek, olyan forgatókönyvek támogatása érdekében, mint például két egész szám elosztása, hogy double-t kapjunk, vagy egy egész számhalmaz átlagának kiszámítása.
Interfész neve Definiált operátorok
IAdditionOperators<TSelf,TOther,TResult> x + y
IBitwiseOperators<TSelf,TOther,TResult> x & y, 'x | y', x ^ y, és ~x
IComparisonOperators<TSelf,TOther,TResult> x < y, x > y, x <= yés x >= y
IDecrementOperators<TSelf> --x és x--
IDivisionOperators<TSelf,TOther,TResult> x / y
IEqualityOperators<TSelf,TOther,TResult> x == y és x != y
IIncrementOperators<TSelf> ++x és x++
IModulusOperators<TSelf,TOther,TResult> x % y
IMultiplyOperators<TSelf,TOther,TResult> x * y
IShiftOperators<TSelf,TOther,TResult> x << y és x >> y
ISubtractionOperators<TSelf,TOther,TResult> x - y
IUnaryNegationOperators<TSelf,TResult> -x
IUnaryPlusOperators<TSelf,TResult> +x

Megjegyzés:

Néhány illesztő egy ellenőrzött operátort határoz meg a normál, nem ellenőrzött operátor mellett. Az ellenőrzött operátorok ellenőrzött környezetekben vannak meghívva, és lehetővé teszik, hogy egy felhasználó által definiált típus definiálja a túlcsordulás viselkedését. Ha például egy ellenőrzött operátort implementál, CheckedSubtraction(TSelf, TOther)akkor a nem ellenőrzött operátort is implementálnia kell, például Subtraction(TSelf, TOther).

Függvényfelületek

A függvényfelületek olyan általános matematikai API-kat határoznak meg, amelyek szélesebb körben alkalmazhatók, mint egy adott numerikus interfészre. Ezeket az interfészeket mind implementálja a IFloatingPointIeee754<TSelf>, és a jövőben más releváns típusok is implementálhatják őket.

Interfész neve Leírás
IExponentialFunctions<TSelf> Exponenciális függvényeket tesz elérhetővé, amelyek támogatják e^x, e^x - 1, 2^x, 2^x - 1, 10^xés 10^x - 1.
IHyperbolicFunctions<TSelf> Hiperbolikus függvényeket tesz elérhetővé, amelyek támogatják acosh(x), asinh(x), atanh(x), cosh(x), sinh(x)és tanh(x).
ILogarithmicFunctions<TSelf> Feltárja a logaritmikus függvényeket, amelyek támogatják ln(x), ln(x + 1), log2(x), log2(x + 1), log10(x) és log10(x + 1).
IPowerFunctions<TSelf> Az energiafüggvényeket támogatja x^y.
IRootFunctions<TSelf> Gyökérfunkciókat tesz elérhetővé, amelyek támogatják a cbrt(x) és sqrt(x) használatát.
ITrigonometricFunctions<TSelf> Trigonometrikus függvényeket tesz elérhetővé, amelyek támogatják acos(x), asin(x), atan(x), cos(x), sin(x)és tan(x).

Elemzési és formázási felületek

Az elemzés és a formázás a programozás alapvető fogalmai. Gyakran használják őket, amikor a felhasználói bemenetet egy adott típusra konvertálják, vagy egy típust jelenítenek meg a felhasználónak. Ezek a felületek a System névtérben találhatók.

Interfész neve Leírás
IParsable<TSelf> Elérhetővé teszi a T.Parse(string, IFormatProvider) és T.TryParse(string, IFormatProvider, out TSelf) támogatását.
ISpanParsable<TSelf> Elérhetővé teszi a T.Parse(ReadOnlySpan<char>, IFormatProvider) és T.TryParse(ReadOnlySpan<char>, IFormatProvider, out TSelf) támogatását.
IFormattable 1 Támogatást biztosít a következőhöz: value.ToString(string, IFormatProvider).
ISpanFormattable 1 Támogatást biztosít a következőhöz: value.TryFormat(Span<char>, out int, ReadOnlySpan<char>, IFormatProvider).

1Ez a felület nem új, és nem is általános. Azonban minden számtípus a függvény inverz műveletének implementációját képviseli, amelyet IParsable jelöl.

A következő program például két számot vesz fel bemenetként, és egy általános módszerrel olvassa be őket a konzolról, ahol a típusparaméter korlátozott.IParsable<TSelf> Az átlagot egy általános módszerrel számítja ki, amelyben a bemeneti és eredményértékek típusparaméterei korlátozottak, INumber<TSelf>majd megjeleníti az eredményt a konzolon.

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
*/

Lásd még