不受语言影响的 Double.ToString()

21

我正在通过网络传输一个double值,目前我的做法是:

double value = 0.25;
string networkMsg = "command " + value;

networkMsg 在英文中为 0.25,在法语中为 0,25,但当从一台法语计算机切换到一台英文计算机时,一侧将其设为 0.25,而另一侧则试图读取 0,25。

因此,我可以在我的代码中使用区域不变方法。

我发现了一个 Val(networkMsg),无论区域如何,它始终会读取 0.25。

但是我找不到一种确保的将值转换为区域不变的 0.25 的方法。 value.toString("0.0") 行得通吗?


5
请使用这个重载方法:ToString(),并按照以下方式调用:0.25.ToString(CultureInfo.InvariantCulture); - Matthew Watson
为什么不能使用BitConverter.GetBytes Method (Double)将其作为二进制传输? - bansi
@bansi,这会假设网络协议可以轻松更改。如果它是基于文本的协议,那么这种方法就不太可行。 - Marc Gravell
@MarcGravell 这只是一个建议,如果更改协议不难(如果已经实现)或者创建协议的话。 - bansi
@bansi 确实,我是二进制协议的忠实粉丝 - 我不反对它是更好的选择:它也会更可靠(没有舍入误差),并且通常更紧凑(4或8个字节,无论值为何)。原则上我不反对。 - Marc Gravell
我创建了一些扩展方法来获取所有这些类型的不变字符串。那是相当深入的研究。 - SandRock
3个回答

21

使用:

string networkMsg = "command " + value.ToString(CultureInfo.InvariantCulture);
或者:
string networkMsg = string.Format(CultureInfo.InvariantCulture, "command {0}", value);

你需要在文件顶部使用System.Globalization;

注意:如果你需要完全精确,以便可以恢复精确的双倍数,请使用Format解决方案和往返格式{0:R},而不是仅仅使用{0}。你可以使用其他格式字符串,例如{0:N4}将插入千位分隔符并四舍五入到四个小数点(小数点后四位)。


自C# 6.0(2015年)以来,您现在可以使用:

string networkMsg = FormattableString.Invariant($"command {value}");

请注意:文档指出,往返格式“R”不是获取不变值的最佳选择。他们建议使用双精度格式“G17”和浮点格式“G9”。 - SandRock
@SandRock 另外,在 (老的) .NET Framework 4.8 中仍然使用旧的 .ToString,而在 .NET Core (自 .NET Core 3.0 开始)及其后代 .NET 中,则使用更符合 IEEE 标准的格式。 "R" 究竟做了什么取决于这个! - Jeppe Stig Nielsen

14

格式化字符串中的"0.0"中的.实际上并不表示"点号",它表示"小数分隔符",在法国和其他几个欧洲文化中是,。你可能想要使用:

value.ToString(CultureInfo.InvariantCulture)
或者
value.ToString("0.0", CultureInfo.InvariantCulture)

了解更多信息,您可以通过检查 fr 文化来查看这个(以及许多其他内容):

var decimalSeparator = CultureInfo.GetCultureInfo("fr")
            .NumberFormat.NumberDecimalSeparator;

1
不变文化使用什么十进制分隔符和其余内容? - f1wade
@f1wade 不变文化基于英语,并使用“.”作为小数分隔符,以及“,”作为所谓的组分隔符。 - Jeppe Stig Nielsen

4

将不变的文化设置为格式提供程序:

value.ToString(CultureInfo.InvariantCulture);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接