I have a JS array with floats like so [0.0028808217, -0.027968751, -0.029748825]
and I transform it to a Float32 Buffer with the following function:
function toFloat32Buffer(array) {
return Buffer.from(new Float32Array(array).buffer)
}
The issue I'm facing is making the conversion from the Float32 Buffer back to a JS array, so I can use the same values as the original array.
I've tried
function toJSArray(buffer) {
const newBuffer = Buffer.from(buffer)
const floatArray = new Float32Array(newBuffer)
return Array.from(floatArray)
}
function toFloat32Buffer(arr) {
return Buffer.from(new Float32Array(arr).buffer)
}
const array = [0.0028808217, -0.027968751, -0.029748825]
const bufferFromFloat32 = toFloat32Buffer(array);
const array2 = toJSArray(bufferFromFloat32);
console.log('array', array)
console.log('array2', array2)
array
and array2
have different values. How should I transform back the buffer to get the same values as the original array? I'm running this in NodeJS
CodePudding user response:
Rewrite your toJsArray
function to:
function toJSArray(buffer) {
return new Float32Array(buffer.buffer);
}
The buffer
property of buffer returns the underlying ArrayBuffer of the buffer.
But as @Matt mentioned in his comment:
Javascript numbers are double-precision 64-bit. I don't think you can get back the precision that is removed converting to 32bit, short of storing it somewhere else. – Matt
For more details: buff.buffer
CodePudding user response:
Here is the fixed code to convert a JavaScript array to a Float32Array, then to a buffer, and back:
function toFloat32Array(buffer) {
return new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / Float32Array.BYTES_PER_ELEMENT)
}
function toFloat32Buffer(array) {
return Buffer.from(new Float32Array(array).buffer)
}
function fromFloat32Buffer(buffer) {
return toFloat32Array(buffer)
}
And here's an example of how you can use these functions:
const array = [1, 2, 3, 4, 5];
const float32Buffer = toFloat32Buffer(array);
console.log(float32Buffer); // <Buffer 00 00 80 3f 00 00 00 40 00 00 40 40 00 00 40 C0>
const float32Array = fromFloat32Buffer(float32Buffer);
console.log(float32Array); // Float32Array [ 1, 2, 3, 4, 5 ]
const originalArray = Array.from(float32Array);
console.log(originalArray); // [ 1, 2, 3, 4, 5 ]
CodePudding user response:
This is alternative solution. Considering using "unsafe" alloc, could be safer in terms of knowing what exactly are you doing. You can also use the var size as a parameter to be more precise, depending on the data you manage
function bufferToArray(buffer, size) {
let arr = [];
for (let i = 0; i < buffer.length / size; i )
arr.push(buffer.readDoubleLE(i * size));
return arr;
}
function arrayToBuffer(arr, size) {
const buffer = Buffer.allocUnsafe(size * arr.length);
arr.map((val, index) => buffer.writeDoubleLE(val, size * index));
return buffer;
}
let array = [0.0028808217, -0.027968751, -0.029748825];
const size = Float64Array.BYTES_PER_ELEMENT; // double-precision
const buffer = arrayToBuffer(array, size);
const array2 = bufferToArray(buffer, size);
console.log(array); // [0.0028808217, -0.027968751, -0.029748825]
console.log(array2); // [0.0028808217, -0.027968751, -0.029748825]