使用 NodeJS N-API 计算浮点值时出现问题

Issue while calculating float value using NodeJS N-API

大家好,

来自网络开发世界。我目前正在尝试编写一些 C 代码,将 RGB 值转换为 NodeJS 可以通过 N-API 使用的 XYZ 值。我遇到的问题是关于 浮点计算 。以下是我的问题的解释:

基于下面的 C 代码,此代码试图将 RGB 值转换为 XYZ 值。

char * colorType = getStringValue(env, funcParams[2], SPACELen);
// m is either the value srgb | adobeRgb
Matrix m = getEnumFromStr(colorType);
Rgb * rgb = getRGBFromJSObj(env, funcParams[0]);
xyz = generateXyzFromRgb(rgb, m);

我正在使用这个 JS 片段来调用我的库

const rgb = {
  r: 255,
  g: 255,
  b: 255
};

const xyz = lib.getXyzFromRgb(rgb, "srgb", 10000);
expect(xyz).to.be.deep.equal({
  x: 0.9504,
  y: 1,
  z: 1.0888
});

如果一切正常,输出应该如下所示

{
 x: 0.9504,
 y: 1,
 z: 1.0888 
}

然而我的输出是这个

{
 x: 0.9502,
 y: 0.9997,
 z: 1.0886 
}

如您所见,输出完全错误。 然而,这个错误的输出只发生在我的本地机器上 (OSX),并且只发生在我尝试使用 JS 片段进行转换时。

确实,当我试图运行直接通过Xcode用下面这段代码进行转换时,输出是正确的

// RGB and & m variable is outputing the same value as the conversion done by the C code above
xyz = generateXyzFromRgb(rgb, m);

此外,当我试图通过 travis 调用 JS 代码时,它也 运行ning OSX 和 Ubuntu 通过 Docker JS代码也输出正确的值

它是否与硬件或我编译库的方式更相关?

提前致谢。

在 javascript v8 引擎中。实际上只存在smi和double。 readFloatBE:当 float 传递给 v8 时,float 将被转换为 double。 当你出去四舍五入时,它会提升到两倍。

首先,如果真的想像C那样取值,需要手动指定四舍五入的数字,然后用Number.prototype.toPrecision函数四舍五入重新实例化Number对象:

供您参考:

var v = 5.2
var buffer = new Buffer(5)
buffer.writeFloatBE(v)
var g = buffer.readFloatBE()

console.log(v)
console.log(g)
console.log(v==g)
console.log(Number(g.toPrecision(5)))

确实,post by Pointy and user10683038 JavaScript 数字是 64 位。

当我编写此功能时,使用的数字类型是 float(乍一看并没有考虑制作 Node 模块)。后来我决定使用如下所示的小 util 方法将 float 转换为 double

double v = *(double *) arg;
status = napi_create_double(env, v, &value);

奇怪的是似乎我在进行此转换时可能随机丢失小数精度,而它不应该(32 位到 64 位)或者我可能遗漏了一些东西。

稍后我重构了相同的代码,但这次是 使用 double 代替,它按预期工作。非常感谢大家。

注意:当我在 NodeJS 绑定代码库中使用上面的方法代码时,我很惊讶我之前没有遇到小数精度错误。