JavaScript的Number採用64位元的IEEE 754標準來表示整數和浮點數數值,其中整數的安全範圍在-253 - 1253 - 1之間。換句話說,Node.js既不能直接使用到32位元的整數,同時也無法使用64位元的整數。因此,如果要拿Node.js來做一些稍微複雜的計算,就需要撰寫額外的程式來處理資料型態的部份,進而影響到執行效能。



int64-napi

int64-napi是一個使用Node.js 8之後才支援的N-API所開發的模組,使用Rust語言原生的i64型態來直接進行64位元的整數運算,可以將效能的影響減到最低。

npmjs.com

npm 安裝指令

npm install int64-napi

使用方法

首先,一個64位元的整數可以用以下幾種不同的資料型別來建立:

  • 其它Int64的實體。
  • 一個53位元的整數。
  • 十進制數值的字串。
  • 0x開頭的十六進制數值的字串。
  • 0o開頭的八進制數值的字串。
  • 0b開頭的二進制數值的字串。
  • 一個存著8個位元組資料的Buffer。
靜態函數的用法
Random
import { random } from "int64-napi";

const n = random(9876543210, "12345678901234"); // 5724595911391
Add
import { add } from "int64-napi";

const n = add("0x0000000000000001", 0x00000002); // 1 + 2 = 3
Subtract
import { subtract } from "int64-napi";

const n = subtract(1, 2); // 1 - 2 = -1
multiply
import { multiply } from "int64-napi";

const n = multiply(2, 6); // 2 * 6 = 12
divide
import { divide } from "int64-napi";

const n = divide(6, 4); // 6 / 4 = 1
mod
import { mod } from "int64-napi";

const n = mod(6, 4); // 6 % 4 = 2
shiftLeft
import { shiftLeft } from "int64-napi";

const n = shiftLeft(0b00101, 2); // 0b000101 << 2 = 0b010100
shiftRight
import { shiftRight } from "int64-napi";

const n1 = shiftRight(0b0101, 2); // 0b0101 >> 2 = 0b0001
const n2 = shiftRight(0b0110, 1); // 0b0110 >> 1 = 0b0011
const n3 = shiftRight("0b1111111111111111111111111111111111111111111111111111111111111011", 1); // 0b1111111111111111111111111111111111111111111111111111111111111011 >> 1 = 0b1111111111111111111111111111111111111111111111111111111111111101
shiftRightUnsigned
import { shiftRightUnsigned } from "int64-napi";

const n = shiftRightUnsigned("0b1111111111111111111111111111111111111111111111111111111111111011", 32); // 0b1111111111111111111111111111111111111111111111111111111111111011 >>> 32 = 0b0000000000000000000000000000000011111111111111111111111111111111
rotateRight
import { rotateRight } from "int64-napi";

const n = rotateRight("0x0000000080000100", 20); // 0x0010000000000800
rotateLeft
import { rotateLeft } from "int64-napi";

const n = rotateLeft("0x0010000000000800", 20); // 0x0000000080000100
and
import { and } from "int64-napi";

const n = and("0x000000000000FFFF", "0x0123456789ABCDEF"); // 0x000000000000CDEF
or
import { or } from "int64-napi";

const n = or("0x0000FFFF0000FFFF", "0xFFFFFFFFFFFF0000"); // 0xFFFFFFFFFFFFFFFF
xor
import { xor } from "int64-napi";

const n = xor("0x0000FFFF0000FFFF", "0xFFFFFFFFFFFF0000"); // 0xFFFF0000FFFFFFFF
nand
import { nand } from "int64-napi";

const n = nand("0x000000000000FFFF", "0x0123456789ABCDEF"); // 0xFFFFFFFFFFFF3210
nor
import { nor } from "int64-napi";

const n = nor("0x0000FFFF0000FFFF", "0xFFFFFFFFFFFF0000"); // 0x0000000000000000
xnor
import { xnor } from "int64-napi";

const n = xnor("0x0000FFFF0000FFFF", "0xFFFFFFFFFFFF0000"); // 0x0000FFFF00000000
not
import { nor } from "int64-napi";

const n = nor("0x0000FFFF0000FFFF", "0xFFFFFFFFFFFF0000"); // 0x0000000000000000
eq(等於)
import { eq } from "int64-napi";

const n = eq("0x0000FFFF0000FFFF", "281470681808895"); // true
ne(不等於)
import { ne } from "int64-napi";

const n = ne("0x0000FFFF0000FFFF", "0x0000FFFF00000000"); // true
gt(大於)
import { gt } from "int64-napi";

const n = gt("0x0000FFFF0000FFFF", "0x0000FFFF00000000"); // true
gte(大於等於)
import { gte } from "int64-napi";

const n = gte("0x0000FFFF0000FFFF", "0x0000FFFF00000000"); // true
lt(小於)
import { lt } from "int64-napi";

const n = lt("0x0000FFFF0000FFFF", "0x0000FFFF0000FFFF"); // false
lte(小於等於)
import { lte } from "int64-napi";

const n = lte("0x0000FFFF0000FFFF", "0x0000FFFF0000FFFF"); // true
comp(比較)

若第一個參數大於第二個參數,回傳1
若第一個參數小於第二個參數,回傳-1
若第一個參數等於第二個參數,回傳0

import { comp } from "int64-napi";

const a = comp("0x0000FFFF0000FFFF", "0x0000FFFF0000FFFF"); // 0
const b = comp("0x0000FFFF0000FFFF", "0x0000FFFF00000000"); // 1
const c = comp("0x0000FFFF00000000", "0x0000FFFF0000FFFF"); // -1
物件方法的用法
建立物件實體
import { Int64 } from "int64-napi";

const i64 = new Int64(1);
物件方法

物件方法的種類和靜態函數大致相同,請參考以下範例:

import { Int64 } from "int64-napi";

const i64 = new Int64(1);
const n1 = i64.add(1).multiply(3).subtract(3).divide(3).toDecimal(); // "1"

i64.set("0xFFFF000000000000");
const n2 = i64.shiftLeft(8).shiftRight(56).toHex(true); // "0xffffffffffffffff"

i64.set("0xFFFF000000000000");
const n3 = i64.shiftLeft(8).shiftRightUnsigned(56).toHex(true); // "0x00000000000000ff"

i64.set("0x000000010001");
const n4 = i64.rotateRight(8).toHex(true); // "0x0100000000000100"

i64.set("0x0000FFFFFFFF0000");
const n51 = i64.toHex(true); // "0x0000ffffffff0000"
const n52 = i64.toHex(); // "ffffffff0000"
const n53 = i64.toDecimal() + 1; // "2814749766451201"
const n54 = i64.toNumber() + 1; // 281474976645121

Int64的物件是可變可被重複使用的,呼叫方法可能會導致它所表示的64位元整數值被改變。

要複製Int64的物件,可以這樣寫:

const i64_2 = i64.clone();