G9
我试图了解C# 中格式说明符在处理往返浮点数时的实用性。
简而言之,C#12 一书中提到,这G9
有助于避免在将 a 转换float
为 astring
并转换回 a时出现精度损失float
(第 324 页)。但我找不到一个例子来说明G9
格式化成功保持相等性,而默认格式化会失败的情况。
例如:
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));
}
}
给我
Default Formatting:
Original: 0.1
Formatted: 0.1
Round-trip Equal: True
G9 Formatting:
Original: 0.1
Formatted: 0.100000001
Round-trip Equal: True
我期待着这样的事情:
Default Formatting:
Original: 0.1
Formatted: 0.100000000001
Round-trip Equal: False
G9 Formatting:
Original: 0.1
Formatted: 0.1
Round-trip Equal: True
您的观察是正确的。
Single.ToString
不带任何参数的调用确实可以往返数字。根据的文献
ToString()
,从标准数字格式字符串来看,对于
float
,单独的“G”没有任何精度,将使用所需的精度来往返数字。Single
请注意,它确实说它将在.NET Framework上使用 G7 ,这可能是本书作者谈到使用 G9 的原因。
另请参阅这个非常古老的答案,其中引用了的文档
Single.ToString()
,与今天所说的不同。因此“G9”的这个目的实际上是有记录的。
专业提示:借助现代计算能力,您实际上可以轻松测试所有可能的浮点值。遗憾的是,双精度仍然遥不可及。
这是一些快速而粗糙的并行代码,在我的计算机上运行大约需要 2 分钟。
使用 G7 格式时,67% 的可能值不会往返(这是 .Net Framework 中的默认值)。使用 G8 时,1.5% 不会往返。使用 G9 时,不会出现任何错误(应该是当前默认值)。这些值被低估了,因为我懒得考虑 NaN。