我正在将值序列化为 XML 文档。当我序列化 adouble
时,我想确保我不会丢失任何精度,并且文化不会干扰。或者我没有想到的任何其他“陷阱”。
同样对于DateTime
,我ToBinary()
用来获取一个序列化非常安全的值。
那么,double
在 C# 中序列化/反序列化值的最佳方法是什么?
我正在将值序列化为 XML 文档。当我序列化 adouble
时,我想确保我不会丢失任何精度,并且文化不会干扰。或者我没有想到的任何其他“陷阱”。
同样对于DateTime
,我ToBinary()
用来获取一个序列化非常安全的值。
那么,double
在 C# 中序列化/反序列化值的最佳方法是什么?
为了解析回确切的值,您应该使用G17
格式说明符,如此处所述:
d.ToString("G17")
或者
$"{d:G17}"
请注意,这可能无法在 .NET Core 3.0 以下的版本上往返。
下面的原始答案; 提到的"r"
格式说明符实际上有一个错误,因此文档不正确。
往返格式说明符“r”保证如果你double.Parse
在字符串上使用,你将得到完全相同的值:
d.ToString("r")
这也处理无穷大:
如果 value 是 Double.PositiveInfinity 或 Double.NegativeInfinity,则此方法分别返回字符串 INF 或 -INF。
BitConverter.GetBytes(myValue)
将给出一个字节数组,然后可以在不损失精度的情况下对其进行序列化。
看起来这应该可行。根据我的测试,它还可以往返于无穷大和 NaN 等特殊值。
static string SerializeDouble(double d)
{
return d.ToString("G17", CultureInfo.InvariantCulture);
}
static double DeserializeDouble(string s)
{
return double.Parse(s, CultureInfo.InvariantCulture);
}
"G17"
?相关报价(在本文发表时):
请注意,当与 Double 值一起使用时,“G17”格式说明符可确保原始 Double 值成功往返。这是因为 Double 是符合 IEEE 754-2008 的双精度 (binary64) 浮点数,最多可提供 17 位有效数字的精度。我们建议使用它而不是“R”格式说明符,因为在某些情况下,“R”无法成功地往返双精度浮点值。
CultureInfo.InvariantCulture
?这会处理任何会破坏您的往返行程的特定于文化的格式。例如,这个代码片段给出了一些非常不受欢迎的结果!
double d0 = Math.PI;
Console.WriteLine("d0: " + d0); // prints 3.14159265358979
// Serialize in America
string s = d0.ToString("G17", new CultureInfo("en-us"));
Console.WriteLine("s: " + s); // prints 3.1415926535897931
// Deserialize in Germany
double d1 = double.Parse(s, new CultureInfo("de-de"));
Console.WriteLine("d1: " + d1); // prints 3.14159265358979E+16