如何使用 Node.js 将 64 位浮点数正确截断为 32 位截断浮点数并返回(降低精度)?
How do I properly truncate a 64 bit float to a 32 bit truncated float and back (dropping precision) with Node.js?
所以显然没有 32 位浮点数,但如果我们试图有效地存储大数据并且我们的许多值是不大于 100,000 的浮点数且恰好有 2 位小数,那么存储 64 位值是有意义的通过删除代表我们不需要的精度的位,在 32 位中。
我尝试通过像这样简单地写入 64 位 BE 浮点缓冲区并分割前 4 个字节来做到这一点:
// float32 = Number between 0.00 and 100000.00
const setFloat32 = (float32) => {
b64.writeDoubleBE(float32, 0) // b64 = 64 bit buffer
b32 = b64.slice(0, 4)
return b32;
}
并通过添加 4 个空字节来读取它:
// b32 = the 32 bit buffer from the previous func
const readFloat32 = (b32) => {
// b32Empty = empty 32 bit buffer
return Buffer.concat([b32, b32Empty]).readDoubleBE(0);
}
但是这个修改后的小数点如下:
1.85 => 1.8499994277954102
2.05 => 2.049999237060547
如何修正我的方法以正确执行此操作,并以最有效的方式执行此操作以提高读取速度?
如果您只想保留两位小数的精度,您可以将您的值转换为移位整数并存储:
function shiftToInteger(val, places) {
// multiply by a constant to shift the decimals you want to keep into
// integer positions, then use Math.round() or Math.floor()
// to truncate the rest of the decimals - depending upon which behavior you want
// then return the shifted integer that will fit into a U32 for storage
return Math.round(val * (10 ** places));
}
这将创建一个移位整数,然后可以将其存储在 32 位值中(具有您描述的值限制),例如 Uint32Array
或 Int32Array
。要在从存储中检索它时使用它,然后将它除以 100 以将其转换回标准 Javascript 浮点数以供使用。
关键是将您想要保留的任何小数精度转换为整数,以便您可以将其存储在 non-float 类型的值中,该值刚好足以满足您的最大预期值。您可以提高存储效率,因为您使用所有存储位来获得所需的精度,而不是在不需要保留的小数精度上浪费大量不必要的存储位。
这是一个例子:
function shiftToInteger(val, places) {
return Math.round(val * (10 ** places));
}
function shiftToFloat(integer, places) {
return integer / (10 ** places);
}
let x = new Uint32Array(10);
x[0] = shiftToInteger(1.85, 2);
console.log(x[0]); // output shifted integer value
console.log(shiftToFloat(x[0], 2)); // convert back to decimal value
所以显然没有 32 位浮点数,但如果我们试图有效地存储大数据并且我们的许多值是不大于 100,000 的浮点数且恰好有 2 位小数,那么存储 64 位值是有意义的通过删除代表我们不需要的精度的位,在 32 位中。
我尝试通过像这样简单地写入 64 位 BE 浮点缓冲区并分割前 4 个字节来做到这一点:
// float32 = Number between 0.00 and 100000.00
const setFloat32 = (float32) => {
b64.writeDoubleBE(float32, 0) // b64 = 64 bit buffer
b32 = b64.slice(0, 4)
return b32;
}
并通过添加 4 个空字节来读取它:
// b32 = the 32 bit buffer from the previous func
const readFloat32 = (b32) => {
// b32Empty = empty 32 bit buffer
return Buffer.concat([b32, b32Empty]).readDoubleBE(0);
}
但是这个修改后的小数点如下:
1.85 => 1.8499994277954102
2.05 => 2.049999237060547
如何修正我的方法以正确执行此操作,并以最有效的方式执行此操作以提高读取速度?
如果您只想保留两位小数的精度,您可以将您的值转换为移位整数并存储:
function shiftToInteger(val, places) {
// multiply by a constant to shift the decimals you want to keep into
// integer positions, then use Math.round() or Math.floor()
// to truncate the rest of the decimals - depending upon which behavior you want
// then return the shifted integer that will fit into a U32 for storage
return Math.round(val * (10 ** places));
}
这将创建一个移位整数,然后可以将其存储在 32 位值中(具有您描述的值限制),例如 Uint32Array
或 Int32Array
。要在从存储中检索它时使用它,然后将它除以 100 以将其转换回标准 Javascript 浮点数以供使用。
关键是将您想要保留的任何小数精度转换为整数,以便您可以将其存储在 non-float 类型的值中,该值刚好足以满足您的最大预期值。您可以提高存储效率,因为您使用所有存储位来获得所需的精度,而不是在不需要保留的小数精度上浪费大量不必要的存储位。
这是一个例子:
function shiftToInteger(val, places) {
return Math.round(val * (10 ** places));
}
function shiftToFloat(integer, places) {
return integer / (10 ** places);
}
let x = new Uint32Array(10);
x[0] = shiftToInteger(1.85, 2);
console.log(x[0]); // output shifted integer value
console.log(shiftToFloat(x[0], 2)); // convert back to decimal value