У меня есть JS-массив с плавающей запятой [0.0028808217, -0.027968751, -0.029748825]
, и я преобразовываю его в буфер Float32 с помощью следующей функции:
function toFloat32Buffer(array) {
return Buffer.from(new Float32Array(array).buffer)
}
Проблема, с которой я столкнулся, заключается в преобразовании из буфера Float32 обратно в массив JS, поэтому я могу использовать те же значения, что и исходный массив.
я пробовал
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.info('array', array)
console.info('array2', array2)
array
и array2
имеют разные значения. Как мне преобразовать буфер, чтобы получить те же значения, что и исходный массив? Я запускаю это в NodeJS
Я подозреваю, что вы не можете вернуть исходные значения. Исходные числа JavaScript были 64-битными значениями. Когда вы сжимаете их в 32-битные значения, вы неизбежно теряете точность. Вы не можете получить его обратно; биты исчезли.
Javascript числа имеют 64-битную двойную точность. Я не думаю, что вы можете вернуть точность, которая была удалена при преобразовании в 32-битную, за исключением хранения ее где-то еще.
Перепишите свою функцию toJsArray
так:
function toJSArray(buffer) {
return new Float32Array(buffer.buffer);
}
Свойство buffer
буфера возвращает базовый массив буфера ArrayBuffer.
Но, как отметил @Matt в своем комментарии:
Числа Javascript являются 64-битными с двойной точностью. Я не думаю, что ты можешь вернуть точность, удаленную при преобразовании в 32-битную, за исключением хранить его в другом месте. – Мэтт
Подробнее: buff.buffer
Это альтернативное решение. Рассматривая использование 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.info(array); // [0.0028808217, -0.027968751, -0.029748825]
console.info(array2); // [0.0028808217, -0.027968751, -0.029748825]
Поиграйте с конструктором DataView() и используйте аргумент
buffer
и методgetFloat32
для извлечения каждого из значений с плавающей запятой из буфера сtrue
, означающим, что значения должны интерпретироваться соответствующим образом. Возможно, пример непроверенной идеи (скорректируйте соответственно): pastebin.com/ZJTDr3i7