Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
As conversões flutuantes ponto-inteiro agora têm comportamento de saturação em máquinas x86 e x64. O comportamento de saturação significa que, se o valor convertido for muito pequeno ou grande para o tipo de destino, o valor será definido como o valor mínimo ou máximo, respectivamente, para esse tipo.
No .NET 11, este comportamento estende-se a conversões não controladas para sbyte, byte, short, ushort, e char no CoreCLR (incluindo o seu interpretador) e AOT nativo, mas não em Mono. Para detalhes, veja As conversões em ponto flutuante para pequenos tipos integrais estão a saturar.
Comportamento anterior
A tabela a seguir mostra o comportamento anterior ao converter um float ou double valor.
| Converter para ... | Valor de x |
Resultado (anterior) |
|---|---|---|
int escalar e empacotado |
int.MinValue <= x <= int.MaxValue |
(int)x |
< int.MinValue ou > int.MaxValue |
int.MinValue |
|
long escalar e empacotado |
long.MinValue <= x <= long.MaxValue |
(long)x |
< long.MinValue ou > long.MaxValue |
long.MinValue |
|
uint escalar e empacotado |
Qualquer valor | (((long)x << 32) >> 32) |
ulong escalar e empacotado |
<= 2^63 |
(long)x |
> 2^63 |
(long)(x - 2^63) + 2^63 |
Novo comportamento
A tabela a seguir mostra o novo comportamento ao converter um float ou double valor.
| Converter para ... | Valor de x |
Resultado do .NET 9+ |
|---|---|---|
int escalar e empacotado |
int.MinValue <= x <= int.MaxValue |
(int)x |
< int.MinValue |
int.MinValue |
|
> int.MaxValue |
int.MaxValue |
|
NaN |
0 | |
long escalar e empacotado |
long.MinValue <= x <= long.MaxValue |
(long)x |
< long.MinValue |
long.MinValue |
|
> long.MaxValue |
long.MaxValue |
|
NaN |
0 | |
uint escalar e embalado |
0 <= x <= uint.MaxValue |
(uint)x |
x > uint.MaxValue |
uint.MaxValue |
|
x < 0 |
0 | |
ulong escalar e empacotado |
0 <= x <= ulong.MaxValue |
(ulong)x |
x > ulong.MaxValue |
ulong.MaxValue |
|
x < 0 |
0 |
Versão introduzida
.NET 9 Pré-visualização 4
Tipo de mudança de rutura
Esta mudança é uma mudança comportamental.
Razão para a alteração
Esta alteração foi feita para normalizar todas as conversões de vírgula flutuante para inteiro, de modo a terem um comportamento de saturação e a tornar esse comportamento determinístico.
Ação recomendada
Se você confiou nos valores mostrados na seção Comportamento anterior para serem retornados da conversão, mesmo que estivessem incorretos, atualize seu código para esperar os valores mostrados na seção Novo comportamento .
Se a sobrecarga de desempenho do novo comportamento for indesejável para o seu cenário, pode usar, em alternativa, os novos métodos ConvertToIntegerNative<TInteger> de Single, Double e Half, que são rápidos. Na maioria dos casos, o comportamento desses métodos corresponde ao comportamento de conversão flutuante ponto-inteiro anterior. No entanto, esses métodos têm um comportamento específico da plataforma que não é garantido para corresponder ao comportamento de conversão anterior (que já era não determinístico). Em vez disso, esses métodos fazem o que for mais eficiente para a plataforma nativa. Notavelmente, o resultado não é garantido para valores que estão fora do intervalo representável do TInteger tipo.
No caso incomum em que você precisa de desempenho e uma garantia estrita de corresponder ao comportamento de conversão anterior, você pode usar os intrínsecos de hardware específicos da plataforma. Por exemplo, você pode usar Sse.ConvertToInt32(Vetor128.CreateScalar(val)) para manipular (int)val para float. Deve verificar if (Sse.IsSupported) antes de utilizar. O uso desses intrínsecos é complicado, no entanto, porque outras plataformas de destino (como o Arm64) já produzem resultados diferentes.
APIs afetadas
Todas as conversões explícitas e implícitas de vírgula flutuante para inteiro:
-
(int)valondevalé umfloatoudouble Vector.ConvertToInt32(Vector<float> val)-
(long)valondevalé umfloatoudouble Vector.ConvertToInt64(Vector<double> val)-
(uint)valondevalé umfloatoudouble Vector.ConvertToUInt32(Vector<float> val)-
(ulong)valondevalé umfloatoudouble Vector.ConvertToUInt64(Vector<double> val)