Konwersje zmiennoprzecinkowe na liczbę całkowitą są saturujące
Konwersje zmiennoprzecinkowe na liczbę całkowitą mają teraz zachowanie saturujące na maszynach x86 i x64. Zachowanie saturujące oznacza, że jeśli przekonwertowana wartość jest zbyt mała lub duża dla typu docelowego, wartość jest ustawiona odpowiednio na wartość minimalną lub maksymalną dla tego typu.
Poprzednie zachowanie
W poniższej tabeli przedstawiono poprzednie zachowanie podczas konwertowania float
wartości lub double
.
Przekonwertuj na ... | Wartość x |
(Poprzedni) wynik |
---|---|---|
int skalarny i zapakowany |
int.MinValue <= x <= int.MaxValue |
(int)x |
< int.MinValue lub > int.MaxValue |
int.MinValue |
|
long skalarny i zapakowany |
long.MinValue <= x <= long.MaxValue |
(long)x |
< long.MinValue lub > long.MaxValue |
long.MinValue |
|
uint skalarny i zapakowany |
Dowolna wartość | (((long)x << 32) >> 32) |
ulong skalarny i zapakowany |
<= 2^63 |
(long)x |
> 2^63 |
(long)(x - 2^63) + 2^63 |
Nowe zachowanie
W poniższej tabeli przedstawiono nowe zachowanie podczas konwertowania float
wartości lub double
.
Przekonwertuj na ... | Wartość x |
Wynik platformy .NET 9+ |
---|---|---|
int skalarny i zapakowany |
int.MinValue <= x <= int.MaxValue |
(int)x |
< int.MinValue |
int.MinValue |
|
> int.MaxValue |
int.MaxValue |
|
NaN |
0 | |
long skalarny i zapakowany |
long.MinValue <= x <= long.MaxValue |
(long)x |
< long.MinValue |
long.MinValue |
|
> long.MaxValue |
long.MaxValue |
|
NaN |
0 | |
uint skalarny i zapakowany |
0 <= x <= uint.MaxValue |
(uint)x |
x > uint.MaxValue |
uint.MaxValue |
|
x < 0 |
0 | |
ulong skalarny i zapakowany |
0 <= x <= ulong.MaxValue |
(ulong)x |
x > ulong.MaxValue |
ulong.MaxValue |
|
x < 0 |
0 |
Wprowadzona wersja
.NET 9 (wersja zapoznawcza 4)
Typ zmiany powodującej niezgodność
Ta zmiana jest zmianą behawioralną.
Przyczyna wprowadzenia zmiany
Ta zmiana została wprowadzona w celu standaryzacji wszystkich konwersji zmiennoprzecinkowych na liczbę całkowitą w celu zachowania saturyzowania i określenia zachowania.
Zalecana akcja
Jeśli opierasz się na wartościach wyświetlanych w sekcji Poprzednie zachowanie , które mają zostać zwrócone z konwersji, nawet jeśli były one nieprawidłowe, zaktualizuj kod, aby oczekiwał wartości wyświetlanych w sekcji Nowe zachowanie .
Jeśli obciążenie związane z wydajnością nowego zachowania jest niepożądane w danym scenariuszu, możesz użyć nowych ConvertToIntegerNative<TInteger>
metod w przypadku pojedynczych, podwójnych i pół , które są szybkie. W większości przypadków zachowanie tych metod jest zgodne z poprzednim zachowaniem konwersji zmiennoprzecinkowych do liczby całkowitej. Jednak te metody mają zachowanie specyficzne dla platformy, które nie gwarantuje dopasowania poprzedniego zachowania konwersji (które było już niedeterministyczne). Zamiast tego te metody robią wszystko, co jest najbardziej wydajne dla platformy natywnej. W szczególności wynik nie jest gwarantowany dla wartości spoza reprezentowanego zakresu TInteger
typu.
W rzadkich przypadkach, gdy potrzebujesz wydajności i ścisłej gwarancji dopasowania poprzedniego zachowania konwersji, możesz użyć funkcji wewnętrznych sprzętu specyficznych dla platformy. Na przykład można użyć metody Sse.ConvertToInt32(Vector128.CreateScalar(val)) do obsługi (int)val
elementu .float
Należy sprawdzić if (Sse.IsSupported)
przed użyciem. Używanie tych funkcji wewnętrznych jest jednak trudne, ponieważ inne platformy docelowe (takie jak Arm64) już generują różne wyniki.
Dotyczy interfejsów API
Wszystkie jawne i niejawne rzutowania od zmiennoprzecinkowych do liczb całkowitych:
(int)val
gdzieval
tofloat
lubdouble
Vector.ConvertToInt32(Vector<float> val)
(long)val
gdzieval
tofloat
lubdouble
Vector.ConvertToInt64(Vector<double> val)
(uint)val
gdzieval
tofloat
lubdouble
Vector.ConvertToUInt32(Vector<float> val)
(ulong)val
gdzieval
tofloat
lubdouble
Vector.ConvertToUInt64(Vector<double> val)