javascript - 使用逻辑运算符将 Int 编码为字节
问题描述
我最近一直在做一些关于逻辑算术的工作。我想将无符号整数(Uint's)和有符号整数(Int's)编码为字节。
下面是当前将 UInts 转换为字节的代码片段,反之亦然。不幸的是,我在用我的策略编码有符号整数时遇到了一些问题。
将使用这种移位和掩码方法对无符号和有符号整数执行整数编码。
for (let i=0; i<n; i++)
buffer.push((value >>> (i*8)) & 0xFF);
那么我的readInt
-method 有什么问题以及如何解决这个问题?
const buffer = [];
const writeIntN = (value, n) => {
for (let i=0; i<n; i++)
buffer.push((value >>> (i*8)) & 0xFF);
}
const readUint = (n, offset) => {
let v=0;
for (let i=0; i<n; i++)
v |= (buffer[offset++] << (i*8));
return v >>> 0;
}
const readInt = (n, offset) => {
return readUint(n, offset) << (8*n) >> (8*n); // error is here
}
const writeUInt16 = (value) => writeIntN(value, 2);
const readUInt16 = (offset) => readUint(2, offset);
const writeInt16 = (value) => writeIntN(value, 2);
const readInt16 = (offset) => readInt(2, offset);
const writeInt8 = (value) => writeIntN(value, 1);
const readInt8 = (offset) => readInt(1, offset);
writeUInt16(20);
writeInt16(-20);
writeInt8(-42);
console.log(buffer);
console.log(readUInt16(0));
console.log(readInt16(2));
console.log(readInt8(4)); // how?
注意:我知道解码 8,16 位有符号整数的基本操作,但如何readUint
更有效地在 for 循环中获取它?
解码 8 位有符号整数:(buffer[offset++] << 24) >> 24
解码 16 位有符号整数:(((buffer[offset++] << 0) | (buffer[offset++] << 8)) << 16) >> 16
解决方案
那么我的 readInt 方法有什么问题以及如何解决这个问题?
修复:更改(8*n)
为(8*(4-n))
.
const readInt = (n, offset) => {
return readUint(n, offset) << (8*(4-n)) >> (8*(4-n));
}
或者,等效地,
const readInt = (n, offset) => {
let v =0;
for (let i=4-n; i<4; i++)
v |= (buffer[offset++] << (i*8));
return v >> (8*(4-n));
}
JavaScript 位运算符使用 32 位(4 字节)整数。左移 ( <<
) 运算符丢弃左移的位。右移运算符 ( >>
) 传播最左边(符号)位。
console.log();
writeUInt16(20);
writeInt16(-20);
writeInt8(-42);
console.log(buffer);
console.log(readUInt16(0));
console.log(readInt16(2));
console.log(readInt8(4));
[ 20, 0, 236, 255, 214 ]
20
-20
-42
const buffer = [];
const writeIntN = (value, n) => {
for (let i=0; i<n; i++)
buffer.push((value >>> (i*8)) & 0xFF);
}
const readUint = (n, offset) => {
let v=0;
for (let i=0; i<n; i++)
v |= (buffer[offset++] << (i*8));
return v >>> 0;
}
const readInt = (n, offset) => {
return readUint(n, offset) << (8*(4-n)) >> (8*(4-n));
}
const writeUInt32 = (value) => writeIntN(value, 4);
const readUInt32 = (offset) => readUint(4, offset);
const writeInt32 = (value) => writeIntN(value, 4);
const readInt32 = (offset) => readInt(4, offset);
const writeUInt16 = (value) => writeIntN(value, 2);
const readUInt16 = (offset) => readUint(2, offset);
const writeInt16 = (value) => writeIntN(value, 2);
const readInt16 = (offset) => readInt(2, offset);
const writeUInt8 = (value) => writeIntN(value, 1);
const readUInt8 = (offset) => readUint(1, offset);
const writeInt8 = (value) => writeIntN(value, 1);
const readInt8 = (offset) => readInt(1, offset);
writeUInt32(Math.pow(2,32)-1);
writeInt32((1<<31)-1);
writeInt32(-(1<<31));
writeUInt16((1<<16)-1);
writeInt16((1<<15)-1);
writeInt16(-(1<<15));
writeUInt8((1<<8)-1);
writeInt8((1<<7)-1);
writeInt8(-(1<<7));
console.log(buffer);
console.log(readUInt32(0));
console.log(readInt32(4));
console.log(readInt32(8));
console.log(readUInt16(12));
console.log(readInt16(14));
console.log(readInt16(16));
console.log(readUInt8(18));
console.log(readInt8(19));
console.log(readInt8(20));
[
255, 255, 255, 255, 255, 255,
255, 127, 0, 0, 0, 128,
255, 255, 255, 127, 0, 128,
255, 127, 128
]
4294967295
2147483647
-2147483648
65535
32767
-32768
255
127
-128
推荐阅读
- phalcon - registerAutoloaders 必须与 Phalcon\Mvc\ModuleDefinitionInterface 兼容
- c++ - 在读取文件时需要帮助忽略某些行,这样我就不必使用 VScode 将它们包含在计算中
- vb.net - 如何让所有用户看到上传的图像 VB.NET winforms
- gemfire - 如何在 @EnableEntityDefinedRegion 中添加 ComponentScan.Filter
- sidebar - 侧边栏 Docusaurus CSS V2
- terraform - 描述阶段返回阶段,但显示阶段如返回 0 行
- microsoft-teams - 在 Microsoft 团队中创建指向音频通话的深层链接
- python - 多个重叠事件的正则表达式匹配?
- mongodb - mongo中的关系
- javascript - 变量返回 undefined 尽管同一个变量之前返回了它的值