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

时间:2018-11-20 22:43:55

标签: javascript c node.js node.js-addon node.js-napi

大家好,

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

基于下面的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);

此外,当我尝试通过同时运行OSX的travis调用 JS代码和通过Docker在Ubuntu上调用JS代码时,也会输出正确的值

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

谢谢。

2 个答案:

答案 0 :(得分:2)

在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)))

答案 1 :(得分:0)

实际上,Pointyuser10683038发布的JavaScript数字是64位。

在我对该功能进行编码时,使用的数字类型为浮点型(乍一看,我并不打算制造Node模块)。后来我决定使用如下所示的小型util方法将 float转换为double

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

奇怪的是,看来我在进行这种转换时可能会随机地降低小数精度,而本来应该没有(32bit到64bit),或者我可能错过了一些东西。

稍后,我重构相同的代码,但是这次通过使用double 进行重构,它可以正常工作。非常感谢大家。

注意:当我在NodeJS绑定代码库中使用上述方法中的util代码时,我很惊讶我之前没有十进制精度错误。