使用 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 绑定代码库中使用上面的方法代码时,我很惊讶我之前没有遇到小数精度错误。
大家好,
来自网络开发世界。我目前正在尝试编写一些 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 绑定代码库中使用上面的方法代码时,我很惊讶我之前没有遇到小数精度错误。