Преобразования с плавающей запятой к целым числам являются насыщенными

Преобразования с плавающей запятой к целым числам теперь имеют насыщенное поведение на компьютерах x86 и x64. Насыщенность поведения означает, что если преобразованное значение слишком мало или большое для целевого типа, то значение присваивается минимальному или максимальному значению соответственно для этого типа.

Прежнее поведение

В следующей таблице показано предыдущее поведение при преобразовании или float значенииdouble.

Преобразуйте в ... Значение параметра x (Предыдущий) результат
int скалярные и упакованные int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue или > int.MaxValue int.MinValue
long скалярные и упакованные long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue или > long.MaxValue long.MinValue
uint скалярные и упакованные Любое значение (((long)x << 32) >> 32)
ulong скалярные и упакованные <= 2^63 (long)x
> 2^63 (long)(x - 2^63) + 2^63

Новое поведение

В следующей таблице показано новое поведение при преобразовании или float значенииdouble.

Преобразуйте в ... Значение параметра x Результат .NET 9+
int скалярные и упакованные int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue int.MinValue
> int.MaxValue int.MaxValue
NaN 0
long скалярные и упакованные long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue long.MinValue
> long.MaxValue long.MaxValue
NaN 0
uint скалярные и упакованные 0 <= x <= uint.MaxValue (uint)x
x > uint.MaxValue uint.MaxValue
x < 0 0
ulong скалярные и упакованные 0 <= x <= ulong.MaxValue (ulong)x
x > ulong.MaxValue ulong.MaxValue
x < 0 0

Представленные версии

.NET 9( предварительная версия 4)

Тип критического изменения

Это изменение поведения.

Причина изменения

Это изменение было сделано, чтобы стандартизировать все преобразования с плавающей запятой к целым числам, чтобы иметь насыщенное поведение и сделать поведение детерминированным.

Если вы использовали значения, отображаемые в разделе "Предыдущее поведение ", возвращаемые из преобразования, даже если они были неверными, обновите код, чтобы ожидать, что значения, отображаемые в разделе "Новое поведение ".

Если затраты на производительность нового поведения нежелательны для вашего сценария, можно использовать новые ConvertToIntegerNative<TInteger> методы для одного, double и half , которые быстро. В большинстве случаев поведение этих методов соответствует предыдущему поведению преобразования с плавающей запятой к целым числам. Однако эти методы имеют поведение, зависящее от платформы , которое не гарантирует соответствие предыдущему поведению преобразования (которое уже было недетерминированным). Вместо этого эти методы делают все, что наиболее эффективно для собственной платформы. В частности, результат не гарантируется для значений, которые находятся за пределами представляющего диапазона TInteger типа.

В редких случаях, когда требуется производительность и строгая гарантия соответствия предыдущему поведению преобразования, можно использовать встроенные компоненты оборудования для конкретной платформы. Например, для обработки (int)valможно использовать float). Перед использованием необходимо проверить if (Sse.IsSupported) . Однако использование этих встроенных функций сложно, так как другие целевые платформы (такие Arm64) уже дают различные результаты.

Затронутые API

Все явные и неявные приведения из плавающей точки в целое число:

  • (int)val где val находится float или double
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val где val находится float или double
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val где val находится float или double
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val где val находится float или double
  • Vector.ConvertToUInt64(Vector<double> val)