Udostępnij za pośrednictwem


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.

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 gdzie val to float lub double
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val gdzie val to float lub double
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val gdzie val to float lub double
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val gdzie val to float lub double
  • Vector.ConvertToUInt64(Vector<double> val)