次の方法で共有


浮動小数点から整数への変換が飽和している

浮動小数点から整数への変換では、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 Preview 4

破壊的変更の種類

この変更は、動作変更です。

変更理由

飽和動作を発生させ、動作を決定論的にするために、すべての浮動小数点から整数への変換を標準化するためにこの変更が行われました。

変換から返される [以前の動作] セクションに示されている値に依存している場合は、それらが正しくない場合でも、[新しい動作] セクションに示されている値を想定するようにコードを更新します。

新しい動作のパフォーマンス オーバーヘッドが自身のシナリオで望ましくない場合は、SingleDouble、および Half の新しい ConvertToIntegerNative<TInteger> メソッドを使用できます。これは高速です。 ほとんどの場合、これらのメソッドの動作は、以前の浮動小数点から整数への変換動作と一致します。 ただし、これらのメソッドにはプラットフォーム固有の動作があり、以前の変換動作と一致するとは限りません (これは既に非決定論的でした)。 代わりに、これらのメソッドは、ネイティブ プラットフォームにおいて最も効率的な処理を行います。 特に、TInteger 型の表現可能な範囲外の値については、結果は保証されていません。

以前の変換動作に一致するパフォーマンスと厳密な保証が必要な、一般的でないケースでは、プラットフォーム固有のハードウェア組み込みを使用できます。 たとえば、Sse.ConvertToInt32(Vector128.CreateScalar(val)) を使用して、(int)valfloat を処理できます。 使用する前に if (Sse.IsSupported) を確認する必要があります。 ただし、他のターゲット プラットフォーム (Arm64 など) では既に異なる結果が生成されるため、これらの組み込みの使用には注意が必要です。

影響を受ける API

浮動小数点から整数へのすべての明示的キャストと暗黙的キャストは次のとおりです。

  • (int)val (ここで、valfloat または double)
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val (ここで、valfloat または double)
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val (ここで、valfloat または double)
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val (ここで、valfloat または double)
  • Vector.ConvertToUInt64(Vector<double> val)