Les conversions de points flottants en nombres entiers sont saturées
Les conversions de points flottants en nombres entiers ont désormais un comportement saturant sur les machines x86 et x64. La saturation signifie que si la valeur convertie est trop petite ou trop grande pour le type cible, la valeur est fixée à la valeur minimale ou maximale, respectivement, pour ce type.
Comportement précédent
Le tableau suivant montre le comportement précédent lors de la conversion d'une valeur float
ou double
.
Convertir en ... | Valeur de x |
Résultat (précédent) |
---|---|---|
int scalaire et emballé |
int.MinValue <= x <= int.MaxValue |
(int)x |
< int.MinValue ou > int.MaxValue |
int.MinValue |
|
long scalaire et emballé |
long.MinValue <= x <= long.MaxValue |
(long)x |
< long.MinValue ou > long.MaxValue |
long.MinValue |
|
uint scalaire et emballé |
Valeur quelconque | (((long)x << 32) >> 32) |
ulong scalaire et emballé |
<= 2^63 |
(long)x |
> 2^63 |
(long)(x - 2^63) + 2^63 |
Nouveau comportement
Le tableau suivant montre le nouveau comportement lors de la conversion d'une valeur float
ou double
.
Convertir en ... | Valeur de x |
Résultat .NET 9+ |
---|---|---|
int scalaire et emballé |
int.MinValue <= x <= int.MaxValue |
(int)x |
< int.MinValue |
int.MinValue |
|
> int.MaxValue |
int.MaxValue |
|
NaN |
0 | |
long scalaire et emballé |
long.MinValue <= x <= long.MaxValue |
(long)x |
< long.MinValue |
long.MinValue |
|
> long.MaxValue |
long.MaxValue |
|
NaN |
0 | |
uint scalaire et emballé |
0 <= x <= uint.MaxValue |
(uint)x |
x > uint.MaxValue |
uint.MaxValue |
|
x < 0 |
0 | |
ulong scalaire et emballé |
0 <= x <= ulong.MaxValue |
(ulong)x |
x > ulong.MaxValue |
ulong.MaxValue |
|
x < 0 |
0 |
Version introduite
.NET 9 Preview 4
Type de changement cassant
Ce changement est un changement de comportement.
Raison du changement
Cette modification a été apportée pour normaliser toutes les conversions de virgules flottantes en nombres entiers afin d'obtenir un comportement saturé et de rendre ce comportement déterministe.
Action recommandée
Si vous vous attendiez à ce que les valeurs indiquées dans la section Comportement précédent soient renvoyées par la conversion, même si elles étaient incorrectes, mettez à jour votre code pour qu'il s'attende aux valeurs indiquées dans la section Nouveau comportement.
Si la surcharge de performance du nouveau comportement n'est pas souhaitable pour votre scénario, vous pouvez utiliser les nouvelles méthodes ConvertToIntegerNative<TInteger>
sur Single, Double, et Half à la place, qui sont rapides. Dans la plupart des cas, le comportement de ces méthodes correspond au comportement précédent de conversion de virgule flottante en nombre entier. Cependant, ces méthodes ont un comportement spécifique à la plate-forme qui n'est pas garanti pour correspondre au comportement de conversion précédent (qui était déjà non déterministe). Au lieu de cela, ces méthodes font ce qui est le plus efficace pour la plateforme native. Notamment, le résultat n'est pas garanti pour les valeurs qui se situent en dehors de la plage représentable du type TInteger
.
Dans le cas peu fréquent où vous avez besoin de performances et d'une garantie stricte de correspondance avec le comportement de conversion précédent, vous pouvez utiliser les intrinsèques matérielles spécifiques à la plate-forme. Par exemple, vous pouvez utiliser Sse.ConvertToInt32(Vector128.CreateScalar(val)) pour traiter (int)val
pour float
. Vous devez vérifier if (Sse.IsSupported)
avant de l'utiliser. L'utilisation de ces intrinsèques est toutefois délicate, car d'autres plateformes cibles (telles que Arm64) produisent déjà des résultats différents.
API affectées
Tous les casts explicites et implicites de la virgule flottante vers les entiers :
(int)val
oùval
est unfloat
ou undouble
Vector.ConvertToInt32(Vector<float> val)
(long)val
oùval
est unfloat
ou undouble
Vector.ConvertToInt64(Vector<double> val)
(uint)val
oùval
est unfloat
ou undouble
Vector.ConvertToUInt32(Vector<float> val)
(ulong)val
oùval
est unfloat
ou undouble
Vector.ConvertToUInt64(Vector<double> val)