Conversies van floating-point naar integers verzadigen

Conversies van drijvende komma-naar-gehele getallen hebben nu een verzadigingsgedrag op x86- en x64-machines. Verzadigingsgedrag betekent dat als de geconverteerde waarde te klein of groot is voor het doeltype, de waarde is ingesteld op respectievelijk de minimum- of maximumwaarde voor dat type.

In .NET 11 wordt dit gedrag uitgebreid naar ongecontroleerde conversies naar sbyte, byte, short, ushort en char op CoreCLR (inclusief de interpreter ervan) en Native AOT, maar niet op Mono. Zie Conversies van drijvende-kommagetallen naar kleine gehele typen zijn verzadigend.

Vorig gedrag

In de volgende tabel wordt het vorige gedrag weergegeven bij het converteren van een waarde van float of double.

Converteren naar ... Waarde van x (Vorige) resultaat
int scalair en gepakt int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue of > int.MaxValue int.MinValue
long scalair en gepakt long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue of > long.MaxValue long.MinValue
uint scalair en gepakt Alle waarden (((long)x << 32) >> 32)
ulong scalaire en verpakte <= 2^63 (long)x
> 2^63 (long)(x - 2^63) + 2^63

Nieuw gedrag

De volgende tabel toont het nieuwe gedrag bij het converteren van een float- of double-waarde.

Converteren naar ... Waarde van x .NET 9+ resultaat
int scalair en gepakt int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue int.MinValue
> int.MaxValue int.MaxValue
NaN 0
long scalair en gepakt long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue long.MinValue
> long.MaxValue long.MaxValue
NaN 0
uint scalaire en gepakte 0 <= x <= uint.MaxValue (uint)x
x > uint.MaxValue uint.MaxValue
x < 0 0
ulong scalaire en verpakte 0 <= x <= ulong.MaxValue (ulong)x
x > ulong.MaxValue ulong.MaxValue
x < 0 0

Versie toegevoegd

.NET 9 preview 4

Type brekende wijziging

Deze wijziging is een gedragswijziging.

Reden voor wijziging

Deze wijziging is aangebracht om alle conversies van drijvende komma-naar-gehele getallen te standaardiseren om verzadigingsgedrag te hebben en om het gedrag deterministisch te maken.

Als u afhankelijk bent van de waarden die worden weergegeven in de sectie Vorig gedrag die moeten worden geretourneerd door de conversie, zelfs als deze onjuist waren, werkt u de code bij om de waarden te verwachten die worden weergegeven in de sectie Nieuw gedrag .

Als de prestatieoverhead van het nieuwe gedrag ongewenst is voor uw scenario, kunt u in plaats daarvan de nieuwe ConvertToIntegerNative<TInteger> methoden gebruiken voor Single, Double en Half , die snel zijn. In de meeste gevallen komt het gedrag van deze methoden overeen met het vorige drijvende-naar-geheel getal-conversiegedrag. Deze methoden hebben echter platformspecifiek gedrag dat niet gegarandeerd overeenkomt met het vorige conversiegedrag (dat al niet-deterministisch was). In plaats daarvan doen deze methoden wat het meest efficiënt is voor het systeemeigen platform. Het resultaat wordt met name niet gegarandeerd voor waarden die buiten het vertegenwoordigbare bereik van het TInteger type vallen.

In het zeldzame geval dat u prestaties nodig hebt en een strikte garantie voor het overeenkomen van het vorige conversiegedrag, kunt u de platformspecifieke hardware-intrinsieken gebruiken. U kunt bijvoorbeeld Sse.ConvertToInt32(Vector128.CreateScalar(val)) gebruiken om te verwerken (int)val voor float. U moet if (Sse.IsSupported) vóór gebruik controleren. Het gebruik van deze intrinsieke kenmerken is echter lastig, omdat andere doelplatforms (zoals Arm64) al verschillende resultaten opleveren.

Getroffen API's

Alle expliciete en impliciete conversies van kommagetallen naar gehele getallen:

  • (int)val waarbij val een float of double is
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val waar val een float of double is
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val waarbij val een float of double is
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val waarbij val een float of double is
  • Vector.ConvertToUInt64(Vector<double> val)