序列化双精度的最佳方法

时间:2012-06-28 00:06:13

标签: c# serialization

我正在将值序列化为XML文档。当我序列化double时,我想确保我没有失去任何精确度,并且文化不会干扰。或者我没有想到的任何其他“陷阱”。

DateTime类似,我使用ToBinary()来获取序列化非常安全的值。

那么,在C#中序列化/反序列化double值的最佳方法是什么?

4 个答案:

答案 0 :(得分:7)

round-trip format specifier "r"保证如果您对字符串使用double.Parse,您将获得完全相同的值:

d.ToString("r")

答案 1 :(得分:3)

结帐XmlConvert.ToString(double value)

这也处理无穷大:

  

如果value为Double.PositiveInfinity或Double.NegativeInfinity,则为此   method分别返回字符串INF或-INF。

答案 2 :(得分:1)

看起来应该可以。根据我的测试,它还可以往返无穷大和NaN等特殊值。

static string SerializeDouble(double d)
{
    return d.ToString("G17", CultureInfo.InvariantCulture);
}

static double DeserializeDouble(string s)
{
    return double.Parse(s, CultureInfo.InvariantCulture);
}

为什么"G17"

来源:https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings?redirectedfrom=MSDN#GFormatString

相关报价(在撰写本文时):

请注意,当与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

答案 3 :(得分:0)

BitConverter.GetBytes(myValue)将提供一个Byte数组,然后可以序列化而不会损失精度。