当我将浮点数写入缓冲区时,它不会读回相同的值:
> var b = new Buffer(4);
undefined
> b.fill(0)
undefined
> b.writeFloatBE(3.14159,0)
undefined
> b.readFloatBE(0)
3.141590118408203
>
(^C again to quit)
>
为什么?
编辑:
我的工作理论是,因为javascript将所有数字存储为双精度,所以当读取浮点数时,缓冲区实现可能没有正确地将double的其他4个字节归零:
> var b = new Buffer(4)
undefined
> b.fill(0)
undefined
> b.writeFloatBE(0.1,0)
undefined
> b.readFloatBE(0)
0.10000000149011612
>
我认为它告诉我们在小数点后面有7位数字(好吧,实际上是8位),然后就是垃圾。我认为节点缓冲区代码中存在一个读取这些浮点数的错误。这就是我的想法。这是节点版本0.10.26。
答案 0 :(得分:3)
浮点数(“浮点数”)永远不是数字的完全准确表示;这是跨多种语言的常见功能,而不仅仅是JavaScript / NodeJS。例如,在使用float
而不是double
时,我在C#中遇到过类似的内容。
双精度浮点数更准确,更符合您的期望。尝试更改上面的代码,将其写为double,而不是float:
var b = new Buffer(8);
b.fill(0);
b.writeDoubleBE(3.14159, 0);
b.readDoubleBE(0);
这将返回:
3.14159
编辑:
如果您有兴趣了解更多内容,维基百科有关于花车和双打的一些非常好的文章:
第二次编辑:
以下是一些代码,用于说明使用类型化数组的单精度与双精度浮点格式的限制。希望这可以作为这种限制的证据,因为我很难用语言解释:
var floats32 = new Float32Array(1),
floats64 = new Float64Array(1),
n = 3.14159;
floats32[0] = n;
floats64[0] = n;
console.log("float", floats32[0]);
console.log("double", floats64[0]);
这将打印:
float 3.141590118408203
double 3.14159
此外,如果我的理解是正确的,单精度浮点数可以存储多达7个总位(有效数字),而不是小数点后7位数。这意味着它们应该准确最多7位有效数字,与你的结果一致(3.14159
有6位有效数字,3.141590118408203
=>前7位=> 3.141590
=> 3.141590 === 3.14159
)。
答案 1 :(得分:1)
readFloat
在c ++中为implemented,字节的解释方式与编译器存储/读取它们的方式完全相同。我怀疑这里有一个错误。我认为&#34; 7位&#34;是浮动的错误假设。 This answer建议使用6位数字(并且它是std::numeric_limits<float>::digits10
的值),因此readFloatBE
的结果在预期错误范围内