4

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

3
  • Play with the DataView() constructor and use the buffer argument and getFloat32 method to retrieve each of the float values from the buffer with true meaning the values should be interpreted accordingly. Example untested idea example perhaps (adjust accordingly): pastebin.com/ZJTDr3i7 Commented Feb 2, 2023 at 3:41
  • I suspect that you cannot get back the original values. The original JavaScript numbers were 64-bit values. When you squash those into 32-bit values, you of necessity lose precision. You cannot get it back; the bits are gone. Commented Feb 2, 2023 at 3:58
  • 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. Commented Feb 2, 2023 at 4:03

3 Answers 3

4

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

Sign up to request clarification or add additional context in comments.

Comments

1

This is alternative solution. Considering using alloc

 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]

Comments

1

To convert a Buffer to a Float32Array, you typically need to ensure that the buffer's byte length is a multiple of 4, because each float (in a Float32Array) occupies 4 bytes. Here's a straightforward approach to achieve this conversion:

function toJSArray(buf) {
  return new Float32Array(buf.buffer, buf.byteOffset, buf.length / Float32Array.BYTES_PER_ELEMENT);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.