Dela via


Flyttal-till-heltalskonverteringar är mättade

Flyttal-till-heltalskonverteringar har nu ett mättande beteende på x86- och x64-datorer. Mättnadsbeteende innebär att om det konverterade värdet är för litet eller stort för måltypen anges värdet till det lägsta respektive högsta värdet för den typen.

Tidigare beteende

I följande tabell visas det tidigare beteendet när du konverterar ett float eller double ett värde.

Konvertera till ... Värdet för x (Föregående) resultat
int skalär och packad int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue eller > int.MaxValue int.MinValue
long skalär och packad long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue eller > long.MaxValue long.MinValue
uint skalär och packad Valfritt värde (((long)x << 32) >> 32)
ulong skalär och packad <= 2^63 (long)x
> 2^63 (long)(x - 2^63) + 2^63

Nytt beteende

I följande tabell visas det nya beteendet när du konverterar ett float eller double ett värde.

Konvertera till ... Värdet för x .NET 9+ resultat
int skalär och packad int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue int.MinValue
> int.MaxValue int.MaxValue
NaN 0
long skalär och packad long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue long.MinValue
> long.MaxValue long.MaxValue
NaN 0
uint skalär och packad 0 <= x <= uint.MaxValue (uint)x
x > uint.MaxValue uint.MaxValue
x < 0 0
ulong skalär och packad 0 <= x <= ulong.MaxValue (ulong)x
x > ulong.MaxValue ulong.MaxValue
x < 0 0

Version introducerad

Förhandsversion 4 av .NET 9

Typ av icke-bakåtkompatibel ändring

Den här ändringen är en beteendeförändring.

Orsak till ändringen

Den här ändringen gjordes för att standardisera alla konverteringar från flyttal till heltal för att ha mättat beteende och för att göra beteendet deterministiskt.

Om du förlitade dig på de värden som visas i avsnittet Föregående beteende som ska returneras från konverteringen, även om de var felaktiga, uppdaterar du koden för att förvänta dig de värden som visas i avsnittet Nytt beteende .

Om prestandakostnaderna för det nya beteendet inte är önskvärda för ditt scenario kan du använda de nya ConvertToIntegerNative<TInteger> metoderna enkel, dubbel och halv i stället, som är snabba. I de flesta fall matchar beteendet för dessa metoder det tidigare konverteringsbeteendet för flyttal till heltal. Dessa metoder har dock plattformsspecifikt beteende som inte garanteras matcha det tidigare konverteringsbeteendet (som redan var icke-deterministiskt). I stället gör dessa metoder det som är mest effektivt för den inbyggda plattformen. Framför allt garanteras inte resultatet för värden som ligger utanför det representerande intervallet för TInteger typen.

I det ovanliga fallet där du behöver prestanda och en strikt garanti för att matcha det tidigare konverteringsbeteendet kan du använda den plattformsspecifika maskinvaran. Du kan till exempel använda Sse.ConvertToInt32(Vector128.CreateScalar(val)) för att hantera (int)val för float. Du måste kontrollera if (Sse.IsSupported) innan du använder den. Det är dock svårt att använda dessa inbyggda funktioner eftersom andra målplattformar (till exempel Arm64) redan ger olika resultat.

Berörda API:er

Alla explicita och implicita kast från flyttal till heltal:

  • (int)val där val är en float eller double
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val där val är en float eller double
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val där val är en float eller double
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val där val är en float eller double
  • Vector.ConvertToUInt64(Vector<double> val)