Kev*_*vin 4 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)
>
Run Code Online (Sandbox Code Playgroud)
为什么?
编辑:
我的工作理论是,因为 javascript 将所有数字存储为双精度,所以当缓冲区实现读回浮点数时,可能无法正确地将双精度数的其他 4 个字节归零:
> var b = new Buffer(4)
undefined
> b.fill(0)
undefined
> b.writeFloatBE(0.1,0)
undefined
> b.readFloatBE(0)
0.10000000149011612
>
Run Code Online (Sandbox Code Playgroud)
我认为这表明小数点后 7 位数字为零(实际上是 8 位),然后就是垃圾。我认为读取这些浮点数的节点缓冲区代码中存在错误。那就是我所想的。这是节点版本 0.10.26。
浮点数(“floats”)从来都不是数字的完全准确的表示;这是多种语言的共同特征,而不仅仅是 JavaScript / NodeJS。例如,我在 C# 中使用float而不是 时遇到了类似的情况double。
双精度浮点数更准确,应该更好地满足您的期望。尝试更改上面的代码以将双精度型而不是浮点型写入缓冲区:
var b = new Buffer(8);
b.fill(0);
b.writeDoubleBE(3.14159, 0);
b.readDoubleBE(0);
Run Code Online (Sandbox Code Playgroud)
这将返回:
3.14159
Run Code Online (Sandbox Code Playgroud)
编辑:
维基百科有一些关于浮点数和双精度数的非常好的文章,如果您有兴趣了解更多信息:
第二次编辑:
下面是一些代码,说明使用类型化数组的单精度浮点格式与双精度浮点格式的限制。希望这可以作为这种限制的证明,因为我很难用语言解释:
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]);
Run Code Online (Sandbox Code Playgroud)
这将打印:
float 3.141590118408203
double 3.14159
Run Code Online (Sandbox Code Playgroud)
另外,如果我的理解正确的话,单精度浮点数最多可以存储7位总数字(有效数字),而不是小数点后7位。这意味着它们应该精确到总共 7 位有效数字,这与您的结果一致(3.14159有 6 位有效数字,3.141590118408203=> 前 7 位数字 => 3.141590=> 3.141590 === 3.14159)。