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.
Rekommenderad åtgärd
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ärval
är enfloat
ellerdouble
Vector.ConvertToInt32(Vector<float> val)
(long)val
därval
är enfloat
ellerdouble
Vector.ConvertToInt64(Vector<double> val)
(uint)val
därval
är enfloat
ellerdouble
Vector.ConvertToUInt32(Vector<float> val)
(ulong)val
därval
är enfloat
ellerdouble
Vector.ConvertToUInt64(Vector<double> val)