从解析fs.readFile()的Node.js意外数字转换

时间:2015-01-07 17:48:00

标签: javascript node.js parsing

当我读入我的文件时,我得到了意外的浮点值。所以我有一个程序可以累积对象e.g. [{a:0.001}, {b:0.002},....]中元素的分数。分数增加0.001。当我退出时,数组被写入具有以下功能的文件:

function(filename, result, msg)
{
  var fs = require('fs');
  var stream = fs.createWriteStream(filename);
  stream.once('open', function(fd) 
  {
      stream.write(JSON.stringify(result));
      stream.end(function()
      {
        console.log(msg);
      });
  });
}

当我启动程序时,在另一个模块中,对象被读入:

fs.readFile('scoreboard.json', 'utf8', function (err, data) 
{
 console.log(JSON.parse(data));
}

当我最初运行我的脚本时,它会产生预期的结果 - 分数是0.001的倍数。但是当我保存并重新加载对象时,分数会变为:

[{a:0.009000000000000001},{b:0.011000000000000003}]

这是因为fs读写浮点数的方式吗?为了解决这个问题,我应该在加载后将分数显式转换为浮点数并在写入之前将它们转换回字符串吗?

1 个答案:

答案 0 :(得分:1)

这是floating-point个数字的事实。我来看看this answer。它的核心是并非所有数字都可以100%准确地用浮点表示,并且选择下一个最接近的可能表示。

您的问题与fs.readFile无关,您可以通过以下方式轻松查看:

v = 0;
for (var i = 0; i < 30; i++){
    v += 0.001;
    console.log(v);
}

打印

0.001
0.002
0.003
0.004
0.005
0.006
0.007
0.008
0.009000000000000001
0.010000000000000002
0.011000000000000003
0.012000000000000004
0.013000000000000005
0.014000000000000005
0.015000000000000006
0.016000000000000007
0.017000000000000008
0.01800000000000001
0.01900000000000001
0.02000000000000001
0.02100000000000001
0.022000000000000013
0.023000000000000013
0.024000000000000014
0.025000000000000015
0.026000000000000016
0.027000000000000017
0.028000000000000018
0.02900000000000002
0.03000000000000002

如果您需要100%的准确度,则需要选择不必舍入的存储格式。对于您的示例,为什么增加0.001而不是存储整数计数并在加载时乘以0.001