js实现packed
实现 Packed 编码的 JavaScript 方法
Packed 编码通常用于将多个较小的数值高效地存储在一个较大的数值中(如 32 位整数)。以下是几种常见的实现方式:
位操作实现
使用位操作将多个数值打包到一个整数中:
function packNumbers(a, b, c, d) {
return (a << 24) | (b << 16) | (c << 8) | d;
}
function unpackNumbers(packed) {
return [
(packed >> 24) & 0xff,
(packed >> 16) & 0xff,
(packed >> 8) & 0xff,
packed & 0xff
];
}
TypedArray 实现
使用 ArrayBuffer 和 TypedArray 进行更灵活的打包:
function packToBuffer(values, bitsPerValue) {
const buffer = new ArrayBuffer(Math.ceil(values.length * bitsPerValue / 8));
const view = new DataView(buffer);
let bitOffset = 0;
for (const value of values) {
const byteIndex = Math.floor(bitOffset / 8);
const bitIndex = bitOffset % 8;
const remainingBits = 8 - bitIndex;
if (bitsPerValue <= remainingBits) {
view.setUint8(byteIndex, view.getUint8(byteIndex) | (value << bitIndex));
} else {
const lowPart = value & ((1 << remainingBits) - 1);
const highPart = value >> remainingBits;
view.setUint8(byteIndex, view.getUint8(byteIndex) | (lowPart << bitIndex));
view.setUint8(byteIndex + 1, highPart);
}
bitOffset += bitsPerValue;
}
return buffer;
}
字符串打包
将数值打包为紧凑字符串表示:
function packToBase64(numbers) {
const buffer = new Uint8Array(numbers.length * 4);
const view = new DataView(buffer.buffer);
for (let i = 0; i < numbers.length; i++) {
view.setUint32(i * 4, numbers[i]);
}
return btoa(String.fromCharCode(...buffer));
}
function unpackFromBase64(str) {
const binary = atob(str);
const buffer = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) {
buffer[i] = binary.charCodeAt(i);
}
const view = new DataView(buffer.buffer);
const result = [];
for (let i = 0; i < buffer.length; i += 4) {
result.push(view.getUint32(i));
}
return result;
}
性能优化建议
对于需要高性能的场景,可以考虑以下优化:
- 使用 WebAssembly 处理大量数据的打包/解包
- 利用 SIMD 指令(通过 WebAssembly)
- 预分配内存避免频繁的垃圾回收
应用场景示例
Packed 编码常用于:
- 游戏开发中的状态压缩
- 网络协议中的高效数据传输
- 图像处理中的像素数据存储
- 数据库中的紧凑数据存储
选择具体实现方法时应考虑:
- 需要处理的数据类型(整数/浮点数)
- 数值的范围和精度要求
- 目标平台的兼容性需求
- 性能与内存的权衡







