浮点数到整数转换将要饱和

现在,浮点数到整数转换在 x86 和 x64 计算机上具有饱和行为。 饱和行为意味着,如果转换后的值对于目标类型来说太小或太大,则该值分别设置为该类型的最小值或最大值。

旧行为

下表显示了转换 floatdouble 值时的以前行为。

转换为... 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

新行为

下表显示了转换 floatdouble 值时的新行为。

转换为... 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> 方法。 在大多数情况下,这些方法的行为与以前的浮点数到整数转换行为匹配。 但是,这些方法具有平台特定的行为,不能保证此行为与以前的转换行为(已经具有非确定性)匹配。 相反,这些方法会对本机平台执行最高效的操作。 值得注意的是,对于超出 TInteger 类型的可表示范围的值,不能保证结果。

在需要性能并严格保证匹配以前的转换行为的特殊情况下,你可以使用特定于平台的硬件内部函数。 例如,你可以使用 Sse.ConvertToInt32(Vector128.CreateScalar(val)) 处理 float(int)val。 在使用之前,你必须检查 if (Sse.IsSupported)。 但是,使用这些内部函数很棘手,因为其他目标平台(如 Arm64)已经产生了不同的结果。

受影响的 API

从浮点数到整数的所有显式和隐式转换:

  • (int)val,其中 valfloatdouble
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val,其中 valfloatdouble
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val,其中 valfloatdouble
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val,其中 valfloatdouble
  • Vector.ConvertToUInt64(Vector<double> val)