Condividi tramite


Le conversioni da virgola mobile a integer stanno saturando

Ora le conversioni da virgola mobile a integer hanno un comportamento di saturazione nei computer x86 e x64. Il comportamento di saturazione significa che se il valore convertito è troppo piccolo o troppo grande per il tipo di destinazione il valore viene impostato rispettivamente sul valore minimo o massimo per il tipo.

Comportamento precedente

Nella tabella seguente viene illustrato il comportamento precedente durante la conversione di un valore float o double.

Converti in... Valore di x Risultato (precedente)
int scalare e in pacchetto int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue oppure > int.MaxValue int.MinValue
long scalare e in pacchetto long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue oppure > long.MaxValue long.MinValue
uint scalare e in pacchetto Qualsiasi valore (((long)x << 32) >> 32)
ulong scalare e in pacchetto <= 2^63 (long)x
> 2^63 (long)(x - 2^63) + 2^63

Nuovo comportamento

Nella tabella seguente viene illustrato il nuovo comportamento durante la conversione di un valore float o double.

Converti in... Valore di x Risultato di .NET 9+
int scalare e in pacchetto int.MinValue <= x <= int.MaxValue (int)x
< int.MinValue int.MinValue
> int.MaxValue int.MaxValue
NaN 0
long scalare e in pacchetto long.MinValue <= x <= long.MaxValue (long)x
< long.MinValue long.MinValue
> long.MaxValue long.MaxValue
NaN 0
uint scalare e in pacchetto 0 <= x <= uint.MaxValue (uint)x
x > uint.MaxValue uint.MaxValue
x < 0 0
ulong scalare e in pacchetto 0 <= x <= ulong.MaxValue (ulong)x
x > ulong.MaxValue ulong.MaxValue
x < 0 0

Versione introdotta

.NET 9 Preview 4

Tipo di modifica che causa un'interruzione

Questa è una modifica funzionale.

Motivo della modifica

Questa modifica è stata apportata per standardizzare tutte le conversioni da virgola mobile a integer in modo da avere un comportamento di saturazione e rendere il comportamento deterministico.

Se ci si è affidati alla conversione dei valori mostrati nella sezione Comportamento precedente, anche se errati, aggiornare il codice per prevedere i valori mostrati nella sezione Nuovo comportamento.

Se il sovraccarico delle prestazioni è indesiderabile per lo scenario, si possono preferire i metodi ConvertToIntegerNative<TInteger> su Single, Double e Half, che sono veloci. Nella maggior parte dei casi, il comportamento di questi metodi corrisponde al comportamento precedente di conversione da virgola mobile a integer precedente. Tuttavia, questi metodi hanno un comportamento specifico della piattaforma che non è garantito che corrisponda al comportamento di conversione precedente (che già non era deterministico). Questi metodi eseguono invece le operazioni più efficienti per la piattaforma nativa. In particolare, il risultato non è garantito per i valori che non rientrano nell'intervallo rappresentabile del tipo TInteger.

Nel caso insolito in cui servissero prestazioni e una rigorosa garanzia di corrispondenza del comportamento di conversione precedente, è possibile usare gli oggetti intrinseci hardware specifici della piattaforma. Ad esempio, si può usare Sse.ConvertToInt32(Vector128.CreateScalar(val)) per gestire (int)val per float. È necessario verificare if (Sse.IsSupported) prima dell'uso. L'uso di questi oggetti intrinseci è difficile, però, perché altre piattaforme di destinazione (ad esempio Arm64) già producono già diversi.

API interessate

Tutti i cast espliciti e impliciti dal virgola mobile a integer:

  • (int)val dove val è un float o double
  • Vector.ConvertToInt32(Vector<float> val)
  • (long)val dove val è un float o double
  • Vector.ConvertToInt64(Vector<double> val)
  • (uint)val dove val è un float o double
  • Vector.ConvertToUInt32(Vector<float> val)
  • (ulong)val dove val è un float o double
  • Vector.ConvertToUInt64(Vector<double> val)