简体   繁体   English

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

[英]Issue while calculating float value using NodeJS N-API

Hello everyone, 大家好,

Coming from the web dev world. 来自网络开发者世界。 I am currently trying to do some C code which is converting an RGB value to an XYZ value that can be used by NodeJS through N-API. 我目前正在尝试执行一些C代码,该代码将RGB值转换为XYZ值,NodeJS可通过N-API使用它。 The issue that I have is regarding to float calculation . 我有一个关于浮动计算的问题 Below is the explanation of my issue: 以下是我的问题的解释:

Based on this C code below, this code is trying to convert an RGB value to an XYZ value. 基于下面的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);

And I am using this JS snippet to call my library 我正在使用这个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
});

If everything should be all right the output should be like the one below 如果一切正常,输出应该像下面的一样

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

However the output that I have is this one 但是我的输出是这个

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

As you can see the output is totally wrong. 如您所见,输出完全错误。 However this wrong output only happened on my local machine (OSX) and only when I am trying to do the conversion by using the JS snippet. 但是,此错误输出仅在我的本地计算机(OSX)上发生,并且仅在我尝试使用JS代码段进行转换时发生。

Indeed, when I am trying to run the conversion with this piece of code below directly through Xcode the output is correct 确实,当我尝试直接通过Xcode使用下面的这段代码运行转换时, 输出是正确的

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

Moreover when I'm trying to call the JS code through travis which also running OSX and on Ubuntu through Docker the JS code also output the right value . 而且,当我试图通过travis调用JS代码时,travis也运行OSX;在Ubuntu上通过Docker调用JS代码也输出正确的值

Can it be more related to the hardware or the way I am compiling my libraries or else ? 它与硬件或我的库编译方式是否更相关?

Thank you in advance. 先感谢您。

In javascript v8 engine. 在javascript v8引擎中。 Actually only exist smi and double. 实际上只存在smi和double。 readFloatBE: when float pass to v8, the float will be cast to double. readFloatBE:当float传递给v8时,float将被强制转换为double。 it will promote to the double when you go out and rounding into a float. 当您外出并四舍五入时,它将提升为两倍。

First, if you really want to get value like C, you need to manually specify the rounded digits and re-instantiate the Number object with the Number.prototype.toPrecision function rounded up: 首先,如果您确实想要获得C之类的值,则需要手动指定四舍五入的数字,并使用四舍五入的Number.prototype.toPrecision函数重新实例化Number对象:

For your reference: 供你参考:

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

Indeed, as post by Pointy and user10683038 JavaScript numbers are 64 bits. 事实上,作为后由user10683038 JavaScript的数字是64位。

As I coded this feature the numeric type used was float (was not thinking at making a Node module at first glance). 当我对该功能进行编码时,所使用的数字类型为float(乍一看,我并没有考虑制作Node模块)。 Later on I decided to do a conversion from float to double using a small util method like below 后来我决定使用如下所示的小型util方法将float转换为double

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

Strangely it appear that I might have randomly loosing decimal precision while doing this conversion while it should have not (32bit to 64bit) or I might have missing out something. 奇怪的是,在执行此转换时,我可能会随机失去小数精度 ,而本来就不应该(从32bit到64bit),否则我可能会漏掉一些东西。

Later on I refactor the same code but this time by using double instead and it works as it should. 稍后,我重构相同的代码,但是这次使用double来重构,它可以正常工作。 Many thanks to all of you. 非常感谢大家。

Note : As I used this util code above method accross the NodeJS binding codebase I am surprised that I haven't got a decimal precision error earlier. 注意 :当我在NodeJS绑定代码库中使用上述方法中的util代码时,我很惊讶我之前没有十进制精度错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM