飽和的浮點數至整數轉換
浮點數至整數轉換目前在 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)) 來處理 float
的 (int)val
。 使用前您必須先檢查 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)