往返格式说明符"R"的64对32位双解析问题

Tri*_*des 2 c# floating-point 64-bit floating-accuracy

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

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

此测试以32位模式传递,但对于64位模式失败,因为生成的文本为:"51.580132999999996"

我期望这样的舍入问题有无理数或通过等式导出的数字,但这里浮点的长度和精度没有模糊性.

这是在较旧的系统内部,因此将所有内容更改为十进制将需要付出巨大努力.

问题:

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

更新这是有效的,并为ToString("G6")生成不同的输出:

[Fact]
public void ParseText()
{
    var numText = "51.580133";
    double.Parse(numText)
        .ToString("G8")
        .Should().Be(numText);
}
Run Code Online (Sandbox Code Playgroud)

jas*_*ith 5

我从微软那里找到了一个有趣的观点,可以解释这个问题

在某些情况下,如果使用/ platform:x64或/ platform:anycpu开关编译并在64位系统上运行,则使用"R"标准数字格式字符串格式化的Double值不能成功往返.

若要解决此问题,您可以使用"G17"标准数字格式字符串格式化Double值.下面的示例使用"R"格式字符串,其Double值不能成功往返,并且还使用"G17"格式字符串成功地往返原始值.

评论和示例可以在这里找到:https: //msdn.microsoft.com/en-us/library/kfsatb94(v = vs.110).aspx

  • 哇...这是一个非常可怕的错误:( (2认同)