Skip to content

Instantly share code, notes, and snippets.

@nuintun
Last active June 10, 2026 08:41
Show Gist options
  • Select an option

  • Save nuintun/f3b7d36bd8413c962a4637bb0d1dde8d to your computer and use it in GitHub Desktop.

Select an option

Save nuintun/f3b7d36bd8413c962a4637bb0d1dde8d to your computer and use it in GitHub Desktop.
BigInt 和 Bytes 互转
/**
* @module bigint
*/
function getByteLength(value: bigint): number {
if (value === 0n || value === -1n) {
return 1;
}
if (value < 0n) {
value = ~value;
}
let bitLength = 0;
while (value > 0n) {
bitLength++;
value >>= 1n;
}
return Math.ceil(bitLength / 8) + 1;
}
export function bigIntToBytes(value: bigint, littleEndian: boolean = false): Uint8Array {
const byteLength = getByteLength(value);
const bytes = new Uint8Array(byteLength);
if (littleEndian) {
for (let offset = 0; offset < byteLength; offset++) {
const currentBitShift = offset * 8;
bytes[offset] = Number((value >> BigInt(currentBitShift)) & 0xffn);
}
} else {
const highestBitShift = (byteLength - 1) * 8;
for (let offset = 0; offset < byteLength; offset++) {
const currentBitShift = highestBitShift - offset * 8;
bytes[offset] = Number((value >> BigInt(currentBitShift)) & 0xffn);
}
}
return bytes;
}
export function bytesToBigInt(bytes: Uint8Array, littleEndian: boolean = false): bigint {
let value = 0n;
const { byteLength } = bytes;
if (byteLength > 0) {
const maxOffset = byteLength - 1;
const isNegative = (bytes[littleEndian ? maxOffset : 0] & 0x80) !== 0;
if (isNegative) {
for (let offset = 0; offset < byteLength; offset++) {
const byte = bytes[littleEndian ? maxOffset - offset : offset];
value = (value << 8n) | BigInt(byte ^ 0xff);
}
return ~value;
}
for (let offset = 0; offset < byteLength; offset++) {
const byte = bytes[littleEndian ? maxOffset - offset : offset];
value = (value << 8n) | BigInt(byte & 0xff);
}
return value;
}
return value;
}
@nuintun

nuintun commented Jun 10, 2026

Copy link
Copy Markdown
Author
/**
 * @function byteLength
 * @description 计算表示给定 bigint 值所需的最小字节数
 * @param {bigint} value 需要计算字节长度的 bigint 值
 * @returns {number} 表示该值所需的最小字节数
 */
function byteLength(value: bigint): number {
  if (value === 0n || value === -1n) {
    return 1;
  }

  if (value < 0n) {
    value = ~value;
  }

  let bytes = 0;

  while (value >> 64n) {
    bytes += 8;
    value >>= 64n;
  }

  if (value < 0x100n) {
    return bytes + 1;
  }

  if (value < 0x10000n) {
    return bytes + 2;
  }

  if (value < 0x1000000n) {
    return bytes + 3;
  }

  if (value < 0x100000000n) {
    return bytes + 4;
  }

  if (value < 0x10000000000n) {
    return bytes + 5;
  }

  if (value < 0x1000000000000n) {
    return bytes + 6;
  }

  if (value < 0x100000000000000n) {
    return bytes + 7;
  }

  return bytes + 8;
}

/**
 * @function bytesToBigInt
 * @description 将字节数组转换为 bigint 值
 * @param {Uint8Array} bytes 包含数据的字节数组
 * @param {boolean} [littleEndian] 是否使用小端序,默认为 false(大端序)
 * @returns {bigint} 转换后的 bigint 值
 */
function bytesToBigInt(bytes: Uint8Array, littleEndian = false): bigint {
  let value = 0n;

  const { length } = bytes;

  if (littleEndian) {
    for (let offset = length - 1; offset >= 0; offset--) {
      value = (value << 8n) | BigInt(bytes[offset]);
    }
  } else {
    for (let offset = 0; offset < length; offset++) {
      value = (value << 8n) | BigInt(bytes[offset]);
    }
  }

  return value;
}

/**
 * @function bigIntToBytes
 * @description 将 bigint 值转换为字节数组
 * @param {bigint} value 需要转换的 bigint 值
 * @param {boolean} [littleEndian] 是否使用小端序,默认为 false(大端序)
 * @param {number} [minLength] 返回字节数组的最小长度,默认为 0(使用计算出的最小长度)
 * @returns {Uint8Array<ArrayBuffer>} 包含转换后数据的字节数组
 */
function bigIntToBytes(value: bigint, littleEndian = false, minLength = 0): Uint8Array<ArrayBuffer> {
  const length = Math.max(minLength, byteLength(value));
  const bytes = new Uint8Array(length);

  if (littleEndian) {
    for (let offset = 0; offset < length; offset++) {
      bytes[offset] = Number(value & 0xffn);

      value >>= 8n;
    }
  } else {
    for (let offset = length - 1; offset >= 0; offset--) {
      bytes[offset] = Number(value & 0xffn);

      value >>= 8n;
    }
  }

  return bytes;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment