64 与 32 位双解析问题,往返格式说明符“R”

64 vs 32 bit double parsing issue with the round-trip format specifier "R"

提问人:Tristan Rhodes 提问时间:7/28/2017 最后编辑:Tristan Rhodes 更新时间:7/28/2017 访问量:394

问:

我在 .net (4.6.1) 中有一个场景,其中解析 6dp 浮点值的字符串表示形式在 32 位和 64 位模式下会产生不同的结果。

[Fact]
public void ParseTest()
{
    var numText = "51.580133";
    double.Parse(numText)
        .ToString("R")
        .Should().Be(numText);
}

此测试在 32 位模式下通过,但在 64 位模式下失败,因为生成的文本为:“51.5801329999999996”

我预计像这样的四舍五入问题会用无理数或通过方程得出的数字,但这里浮点的长度和准确性没有歧义。

这是在较旧的系统中,因此将所有内容更改为十进制将花费大量精力。

问题:

  1. 为什么会这样?
  2. 有哪些选项可以可靠地将此值四舍五入/截断为 6dp?

更新 这将起作用,并生成与 ToString(“G6”) 不同的输出:

[Fact]
public void ParseText()
{
    var numText = "51.580133";
    double.Parse(numText)
        .ToString("G8")
        .Should().Be(numText);
}
C# 64 位 浮点精度

评论

1赞 Jon Skeet 7/28/2017
那么,您认为问题出在解析还是格式上?请记住,最接近 51.580133 的正好是 51.580132999999999645706338924355804920196533203125。double
1赞 Tim Schmelter 7/28/2017
MSDN:“如果该值已成功分析回相同的数值,则使用常规格式说明符对其进行格式化。如果该值未成功解析回相同的数值,则使用 17 位精度将其格式化为 Double”

答:

5赞 jason.kaisersmith 7/28/2017 #1

我从Microsoft那里发现了这个有趣的观点,可以解释这个问题

在某些情况下,使用“R”标准数字格式化的双精度值 如果使用 /platform:x64 或 /platform:anycpu 切换并在 64 位系统上运行。

要变通解决此问题,您可以使用 “G17”标准数字格式字符串。以下示例使用 “R”格式字符串,其 Double 值不往返 成功,并且还使用“G17”格式字符串成功 往返原始值。

注释和示例可以在此处找到:https://msdn.microsoft.com/en-us/library/kfsatb94(v=vs.110).aspx

评论

2赞 Jon Skeet 7/28/2017
哇。。。这是一个非常可怕的错误:(