4

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

同样对于DateTime,我ToBinary()用来获取一个序列化非常安全的值。

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

4

4 回答 4

8

为了解析回确切的值,您应该使用G17格式说明符,如此所述:

d.ToString("G17")

或者

$"{d:G17}"

请注意,这可能无法在 .NET Core 3.0 以下的版本上往返。


下面的原始答案; 提到的"r"格式说明符实际上有一个错误,因此文档不正确


往返格式说明符“r”保证如果你double.Parse在字符串上使用,你将得到完全相同的值:

d.ToString("r")
于 2012-06-28T00:22:20.043 回答
2

结帐XmlConvert.ToString(双值)

这也处理无穷大:

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

于 2012-06-28T00:20:13.320 回答
1

BitConverter.GetBytes(myValue)将给出一个字节数组,然后可以在不损失精度的情况下对其进行序列化。

于 2012-06-28T00:19:57.990 回答
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
于 2020-08-31T11:58:55.887 回答