缓冲区读写浮动

时间:2014-11-24 04:23:19

标签: javascript node.js

当我将浮点数写入缓冲区时,它不会读回相同的值:

> 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。

2 个答案:

答案 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的结果在预期错误范围内