2

我正在尝试将字节流复制到双精度数组中。字节不一定代表双精度值,双精度数组只是用作存储机制(我意识到这很疯狂,但这是对我们框架的当前限制,我们有一个截止日期)。但是我发现,在某些情况下,将双精度数组复制回字节数组时,数据发生了变化。

我已将其缩小到以下测试用例失败

[TestMethod]
    public void Test()
    {
        var bytes = new byte[]
            {
                24,
                108,
                6,
                14,
                7,
                91,
                242,
                255
            };

        double d = BitConverter.ToDouble(bytes, 0);

        var returnedBytes = BitConverter.GetBytes(d);

        for (int i = 0; i < returnedBytes.Count(); i++)
        {
            Assert.AreEqual(bytes[i], returnedBytes[i]);
        }
    }

我现在意识到有一些底层框架功能阻止我采用这种方法。但是出于兴趣,任何人都可以解释为什么上述测试用例失败了吗?

4

2 回答 2

3

因为您提供的值不是 IEE754 双精度的有效编码 - 至少在小端架构上,这可能是您所拥有的。double您在上面生成的是,NaN它是整个范围的二进制值,不会计算为范围内的双精度值。框架返回一个“标准”或至少是 mutated 也就不足为奇了NaN

如果将 32 位字的顺序颠倒为:

7, 91, 242, 255, 24, 108, 6, 14

您最终可能会得到 4.20332332290442E-241。

或者,颠倒32 位字中字节的顺序:

14, 6, 108, 24, 255, 242, 91, 7

产量 3.22903984511934E-273

最后,反转整个列表(小结尾的 64 位寄存器)

255, 242, 91, 7, 14, 6, 108, 24

产量 4.91380011890093E-191

所以,是的,您需要弄清楚源编码是什么,以及您自己的编码是什么。请注意,无论您是在 32 位还是 64 位模式下运行,这可能会有所不同。

于 2013-10-07T16:10:21.520 回答
1

BitConverter根本不会乱搞这些位——它甚至从不检查它们,所以NaN当它看到一个无意义的值时没有标准被映射。然而,JIT 可能正在生成导致 CPU 与您的位发生冲突的代码。

如果它放入double80 位寄存器,则有一些隐藏的转换正在进行。在伪 C 中:

float80 d = *(float64*)bytes;
*(float64*)bytes = d;

在 80 位寄存器和 64 位存储之间的转换中,CPU 会破坏您的值。

于 2013-10-07T16:15:18.610 回答