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

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

本文关键字:意外 数字 转换 js 解析 fs readFile 节点      更新时间:2023-09-26

当我读取文件时,我得到了意外的浮点值。所以我有一个程序可以累积对象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数字的事实。我会看看这个答案。其核心是并非所有数字都可以用浮点数 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