我正在尝试将字节流复制到双数组中。字节不一定代表double值,double数组只是用作存储机制(我意识到这很疯狂,但它是我们框架的当前限制,我们有一个截止日期)。但是我发现在某些情况下,当将双数组复制回字节数组时,数据已经改变了。
我已将其缩小到以下测试用例失败
[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]);
}
}
我现在意识到有一些底层框架功能阻止我采用这种方法。但是,出于兴趣,任何人都可以解释为什么上述测试用例失败了吗?
答案 0 :(得分:3)
因为你提供的值不是IEE754双倍的有效编码 - 至少在little-endian架构上,这可能就是你所拥有的。您在上面生成的double
是NaN
,这是一整套二进制值,不会计算到范围内的双精度值。框架返回“标准”或至少是变异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位模式下运行,这都可能会有所不同。
答案 1 :(得分:1)
BitConverter
根本不会涉及这些位 - 它甚至从不检查它们,因此当它看到无意义的值时,没有标准的NaN
被映射。但是,JIT可能会生成代码,导致CPU与您的位拧紧。
如果它将double
放在80位寄存器中,则会有一些隐藏的转换。在伪C:
float80 d = *(float64*)bytes;
*(float64*)bytes = d;
在80位寄存器和64位存储器之间的转换中,CPU会破坏您的值。