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

Node.js unexpected number conversion from parsing fs.readFile()

我在读取文件时得到了意外的浮点值。所以我有一个程序可以为我的对象 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 读写浮点数的方式吗?要解决这个问题,我是否应该在加载后显式地将分数转换为浮点数并在写入之前将它们转换回字符串?

这是 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