浮動小数点から整数への変換が飽和している
浮動小数点から整数への変換では、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
破壊的変更の種類
この変更は、動作変更です。
変更理由
飽和動作を発生させ、動作を決定論的にするために、すべての浮動小数点から整数への変換を標準化するためにこの変更が行われました。
推奨される操作
変換から返される [以前の動作] セクションに示されている値に依存している場合は、それらが正しくない場合でも、[新しい動作] セクションに示されている値を想定するようにコードを更新します。
新しい動作のパフォーマンス オーバーヘッドが自身のシナリオで望ましくない場合は、Single、Double、および Half の新しい ConvertToIntegerNative<TInteger>
メソッドを使用できます。これは高速です。 ほとんどの場合、これらのメソッドの動作は、以前の浮動小数点から整数への変換動作と一致します。 ただし、これらのメソッドにはプラットフォーム固有の動作があり、以前の変換動作と一致するとは限りません (これは既に非決定論的でした)。 代わりに、これらのメソッドは、ネイティブ プラットフォームにおいて最も効率的な処理を行います。 特に、TInteger
型の表現可能な範囲外の値については、結果は保証されていません。
以前の変換動作に一致するパフォーマンスと厳密な保証が必要な、一般的でないケースでは、プラットフォーム固有のハードウェア組み込みを使用できます。 たとえば、Sse.ConvertToInt32(Vector128.CreateScalar(val)) を使用して、(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)
.NET