在NodeJS中,如何将一个32位浮点数从Buffer编码为保留原始精度的(JSON)字符串?

4

输入是一个缓冲区,包含单精度浮点数(32位,小端序)。

我想生成的是一个 JSON 字符串,其中包含这些数字,保留相同的值且不改变精度。

问题在于:一旦值存储在 JS 的 number 中,它就被转换为 64 位,引入了精度变化。

例如:

const buffer = Buffer.from("cdcccc3d", "hex"); // cdcccc3d is 0.1 in 32 bits float LE
console.log(buffer.readFloatLE(0)); // 0.10000000149011612 => bad

如何将此值作为字符串获取并保留原始精度而不进行转换?这里是:"0.1"
如果我能够生成包含具有原始精度的数字的JSON字符串,则可以得到奖励分数:{ "value": 0.1 }

0.1无法用IEEE-754浮点数表示,无论是32位还是64位。额外的精度是否会导致任何问题(除了看起来难看之外)? - Thomas
哦,抱歉我的例子不好,我使用了这个网站,告诉我它确切是0.1 https://www.scadacore.com/tools/programming-calculators/online-hex-converter/ 是的,保持精度完全一样是一个强烈的要求,解码后的数字被敏感的数学算法使用。 - Thomas Lulé
1
从32位到64位的转换不会失去任何精度。任何32位浮点数都可以完美地表示为64位浮点数。无论在将该64位浮点数转换为字符串并再次转换回来后是否仍然完全相同,我不确定,但无论如何,差异都是如此之小,以至于当您将其转换回32位浮点数时它几乎消失了。 - Thomas
1个回答

0

小端字节 cd cc cc 3d,在大端序中为 3d cc cc cd,或位 0011 1101 1100 1100 1100 1100 1100 1101。

在 IEEE-754 二进制32位编码中,0 是符号位,011 1101 1 是指数字段位,100 1100 1100 1100 1100 1101 是尾数字段位。

0 符号位表示正数。

指数字段位 011 1101 1 的原始二进制值为 123。指数使用偏置127进行编码,因此表示的指数为 123−127 = −4。

由于指数字段不为零(或全部为1,用于表示无穷大和NaN),因此在尾数字段位前加上1,形成 1100 1100 1100 1100 1100 1101。作为原始二进制,这是13,421,773。尾数使用223的比例进行编码,因此表示的尾数为13,421,773/223

将符号、指数和尾数组合起来,表示的值为+2−4•13,421,773/223=0.100000001490116119384765625。这是精确表示的值,没有误差。因此,您可以看到为其生成的数字“0.10000000149011612”是准确的,就其所涉及的范围而言。


哦,谢谢你,这意味着我对IEEE-754有错误的想法。 - Thomas Lulé

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接