Estou tentando entender a utilidade prática do G9
especificador de formato em C# ao lidar com números de ponto flutuante de ida e volta.
O livro C#12 em poucas palavras menciona que G9
é útil evitar perda de precisão ao converter a float
para a string
e de volta para a float
(página 324). Mas não consigo encontrar um exemplo que mostre um caso em que G9
a formatação tenha sucesso em preservar a igualdade, enquanto a formatação padrão falharia.
Por exemplo:
using System;
class Program
{
static void Main()
{
float originalNumber = 0.1f;
string defaultFormatted = originalNumber.ToString();
float defaultRoundTrip = float.Parse(defaultFormatted);
Console.WriteLine("Default Formatting:");
Console.WriteLine("Original: " + originalNumber);
Console.WriteLine("Formatted: " + defaultFormatted);
Console.WriteLine("Round-trip Equal: " + (originalNumber == defaultRoundTrip));
string g9Formatted = originalNumber.ToString("G9");
float g9RoundTrip = float.Parse(g9Formatted);
Console.WriteLine("\nG9 Formatting:");
Console.WriteLine("Original: " + originalNumber);
Console.WriteLine("Formatted: " + g9Formatted);
Console.WriteLine("Round-trip Equal: " + (originalNumber == g9RoundTrip));
}
}
Me dá
Default Formatting:
Original: 0.1
Formatted: 0.1
Round-trip Equal: True
G9 Formatting:
Original: 0.1
Formatted: 0.100000001
Round-trip Equal: True
Eu esperava algo do tipo:
Default Formatting:
Original: 0.1
Formatted: 0.100000000001
Round-trip Equal: False
G9 Formatting:
Original: 0.1
Formatted: 0.1
Round-trip Equal: True
Suas observações estão corretas. Ligar
Single.ToString
sem argumentos pode realmente fazer roundtrip no número.Da documentação de
ToString()
,A partir de strings de formato numérico padrão , diz-se que para
float
, "G" sozinho, sem nenhuma precisão, usará tanta precisão quanto necessária para fazer o arredondamento do número.Single
Observe que ele diz que usará o G7 no .NET Framework , e é possivelmente por isso que o autor do livro fez essa observação sobre o uso do G9.
Veja também esta resposta muito antiga que cita a documentação para
Single.ToString()
, que é diferente do que diz hoje.Então esse propósito do "G9" foi realmente documentado.
Dica profissional: com o poder de computação moderno, você pode realmente testar facilmente todos os valores de float possíveis. Doubles ainda estão fora de alcance, infelizmente.
Aqui está um código paralelo rápido e prático que roda em ~2 minutos na minha máquina.
Com o formato G7, 67% dos valores possíveis não fazem round trip (era o padrão no .Net Framework). Com o G8, 1,5% não fazem round trip. Com o G9, não há erros (deveria ser o padrão atual). E esses valores são subestimados porque não me incomodei em contabilizar NaNs.