or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

arithmetic.mdbitwise.mdcomparison.mdconversion.mdindex.mdproperties.md
tile.json

conversion.mddocs/

Conversion Operations

Convert BigInteger values to various formats including strings with custom bases and alphabets, arrays, native JavaScript numbers, and JSON, along with support for special and negative bases.

Capabilities

String Conversion

To String

Convert a BigInteger to a string representation in any base.

/**
 * Converts BigInteger to string in specified base
 * @param radix - Number base (default 10). Supports:
 *   - Standard bases: 2-36 (uses 0-9, a-z)
 *   - Large bases: >36 (uses angle bracket notation for digits ≥36)
 *   - Negative bases: Any negative integer
 *   - Special bases: 0 (only for zero), 1, -1
 * @param alphabet - Custom alphabet for digits (default "0123456789abcdefghijklmnopqrstuvwxyz")
 * @returns String representation in specified base
 * @throws Error for base 0 with non-zero numbers
 */
toString(radix?: number, alphabet?: string): string;

Usage Examples:

const bigInt = require('big-integer');

// Default base 10
bigInt("1000000000").toString();  // "1000000000"

// Binary (base 2)
bigInt(255).toString(2);  // "11111111"

// Hexadecimal (base 16)
bigInt("1000000000").toString(16);  // "3b9aca00"

// Octal (base 8)
bigInt(64).toString(8);  // "100"

// Base 36 (using all digits and letters)
bigInt(1000).toString(36);  // "rs"

// Bases larger than 36 use angle brackets
bigInt(567890).toString(100);  // "<56><78><90>"

// Custom alphabet
bigInt(5).toString(2, "aA");  // "AaA" (binary with custom symbols)

// Parsing scientific notation
bigInt("1e9").toString();  // "1000000000"

// Large numbers
bigInt("999999999999999999").toString();  // Preserves full precision

Special Bases:

// Negative base -10
bigInt(12345).toString(-10);  // "28465"

// Base 1 (unary)
bigInt(5).toString(1);   // "11111"
bigInt(-5).toString(1);  // "-11111"

// Base -1 (balanced unary)
bigInt(-15).toString(-1);
// "101010101010101010101010101010" (30 digits)

// Base 0 (only allowed for zero)
bigInt(0).toString(0);  // "0"
try {
  bigInt(1).toString(0);  // Error: Cannot convert nonzero numbers to base 0
} catch (e) {
  console.error(e.message);
}

Important Note on valueOf:

The toString() method should always be used explicitly. Using the + operator or implicit string conversion will trigger valueOf() instead, which converts to a JavaScript number and loses precision:

const big = bigInt("999999999999999999");

// CORRECT: Use toString()
big.toString();  // "999999999999999999" (preserves precision)
String(big);     // "999999999999999999" (also correct)

// INCORRECT: Don't use + operator for string conversion
big + "";  // "1000000000000000000" (loses precision!)

Array Conversion

To Array

Convert a BigInteger to an array representation in a specified base.

/**
 * Converts BigInteger to array of digits in specified radix
 * @param radix - Number base (supports all bases including negative and special)
 * @returns Object with:
 *   - value: Array of digit values in specified base
 *   - isNegative: Boolean indicating if number is negative
 * @throws Error for base 0 with non-zero numbers
 */
toArray(radix: number): { value: number[], isNegative: boolean };

Usage Examples:

// Base 10 array
bigInt("1000000000").toArray(10);
// { value: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0], isNegative: false }

// Hexadecimal array
bigInt("1000000000").toArray(16);
// { value: [3, 11, 9, 10, 12, 10, 0, 0], isNegative: false }

// Base 100 (useful for processing pairs of decimal digits)
bigInt(567890).toArray(100);
// { value: [56, 78, 90], isNegative: false }

// Negative numbers
bigInt(-42).toArray(10);
// { value: [4, 2], isNegative: true }

// Binary array
bigInt(255).toArray(2);
// { value: [1, 1, 1, 1, 1, 1, 1, 1], isNegative: false }

Special Bases:

// Negative base -10
bigInt(12345).toArray(-10);
// { value: [2, 8, 4, 6, 5], isNegative: false }

// Base 1 (unary)
bigInt(5).toArray(1);
// { value: [1, 1, 1, 1, 1], isNegative: false }

bigInt(-15).toArray(1);
// { value: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], isNegative: true }

// Base -1
bigInt(-15).toArray(-1);
// { value: [1, 0, 1, 0, ..., 1, 0], isNegative: false }
// (30 elements alternating 1 and 0)

// Base 0 (only for zero)
bigInt(0).toArray(0);
// { value: [0], isNegative: false }

JavaScript Number Conversion

To JavaScript Number

Convert a BigInteger to a native JavaScript number.

/**
 * Converts BigInteger to native JavaScript number
 * WARNING: Loses precision for numbers outside the safe integer range
 * Safe range: [-9007199254740992, 9007199254740992]
 * @returns JavaScript number (may lose precision)
 */
toJSNumber(): number;

Usage Examples:

// Within safe range
bigInt(100).toJSNumber();  // 100

// Small negative numbers
bigInt(-42).toJSNumber();  // -42

// At the edge of safe range
bigInt(9007199254740992).toJSNumber();  // 9007199254740992 (exact)

// Outside safe range - LOSES PRECISION
bigInt("9007199254740993").toJSNumber();  // 9007199254740992 (lost precision!)
bigInt("18446744073709551616").toJSNumber();  // 18446744073709552000 (imprecise)

// Use case: Converting for display or simple operations
const big = bigInt(42);
const jsNum = big.toJSNumber();
console.log(jsNum * 2);  // 84 (safe for small numbers)

Precision Warning:

JavaScript numbers use IEEE 754 double-precision format, which can only precisely represent integers in the range [-2^53, 2^53] (i.e., [-9007199254740992, 9007199254740992]). Outside this range, precision is lost.

// Check if safe to convert
function safeToConvert(bigInt) {
  const max = bigInt.constructor(9007199254740992);
  const min = bigInt.constructor(-9007199254740992);
  return bigInt.greaterOrEquals(min) && bigInt.lesserOrEquals(max);
}

const small = bigInt(1000);
const huge = bigInt("99999999999999999999");

safeToConvert(small);  // true
safeToConvert(huge);   // false

Value Of

Convert to JavaScript number for use with native operators.

/**
 * Converts to JavaScript number for native arithmetic operators
 * Allows use of +, -, *, /, %, etc. without explicit conversion
 * WARNING: Same precision limitations as toJSNumber()
 * @returns JavaScript number (may lose precision)
 */
valueOf(): number;

Usage Examples:

// valueOf() is called implicitly by JavaScript operators
const a = bigInt(100);
const b = bigInt(200);

// Implicit conversion via valueOf()
a + b;  // 300 (number, not BigInteger)
a * 2;  // 200 (number)
a / b;  // 0.5 (number)

// Comparison operators also use valueOf()
bigInt(100) > 50;   // true
bigInt(42) === 42;  // false (different types)
bigInt(42) == 42;   // true (coercion)

// This is why you should NOT use + for string concatenation
const big = bigInt("999999999999999999");
big + "";  // "1000000000000000000" (valueOf() called, precision lost!)

// Always use toString() explicitly for strings
big.toString();  // "999999999999999999" (correct)

JSON Conversion

To JSON

Convert a BigInteger to a string for JSON serialization.

/**
 * Converts BigInteger to string for JSON serialization
 * Called automatically by JSON.stringify()
 * @returns String representation in base 10
 */
toJSON(): string;

Usage Examples:

// Direct call
bigInt(42).toJSON();  // "42"

// Automatic call during JSON.stringify
const data = {
  id: bigInt("123456789012345678901234567890"),
  count: bigInt(42)
};

JSON.stringify(data);
// '{"id":"123456789012345678901234567890","count":"42"}'

// In arrays
JSON.stringify([bigInt(1), bigInt(2), bigInt(3)]);
// '["1","2","3"]'

// Roundtrip: BigInteger -> JSON -> BigInteger
const original = bigInt("999999999999999999");
const json = JSON.stringify({ value: original });
const parsed = JSON.parse(json);
const restored = bigInt(parsed.value);
// restored equals original (no precision loss)

Practical Use Cases

Base Conversion

/**
 * Convert between different number bases
 */
function convertBase(value, fromBase, toBase) {
  const num = bigInt(value, fromBase);
  return num.toString(toBase);
}

// Binary to hexadecimal
convertBase("11111111", 2, 16);  // "ff"

// Hexadecimal to decimal
convertBase("ff", 16, 10);  // "255"

// Decimal to binary
convertBase("255", 10, 2);  // "11111111"

// Decimal to base 36
convertBase("1000", 10, 36);  // "rs"

Data Serialization

/**
 * Serialize BigInteger for storage
 */
function serialize(bigInt) {
  return {
    value: bigInt.toString(),
    base: 10
  };
}

/**
 * Deserialize BigInteger from storage
 */
function deserialize(data) {
  return bigInt(data.value, data.base);
}

// Use
const original = bigInt("123456789012345678901234567890");
const serialized = serialize(original);
const json = JSON.stringify(serialized);
// Store json in database or send over network

// Later...
const parsed = JSON.parse(json);
const restored = deserialize(parsed);
// restored equals original

Custom Number Systems

/**
 * Roman numeral alphabet (simplified example)
 */
const romanAlphabet = "IVXLCDM";

// Note: This is just for demonstration
// Real Roman numerals don't work as a positional system
function toCustomAlphabet(num, alphabet) {
  const base = alphabet.length;
  const array = num.toArray(base);

  return array.value.map(digit => {
    if (digit < alphabet.length) {
      return alphabet[digit];
    }
    return `<${digit}>`;
  }).join('');
}

// Binary with custom alphabet
bigInt(5).toString(2, "OI");  // "IOI" (101 in binary)

// Hexadecimal with uppercase
bigInt(255).toString(16, "0123456789ABCDEF");  // "FF"

Digit Extraction

/**
 * Extract individual digits from a number
 */
function getDigits(num, base = 10) {
  return num.toArray(base).value;
}

/**
 * Get specific digit at position
 */
function getDigit(num, position, base = 10) {
  const digits = num.toArray(base).value;
  return digits[digits.length - 1 - position] || 0;
}

// Get decimal digits
getDigits(bigInt(12345));  // [1, 2, 3, 4, 5]

// Get ones place
getDigit(bigInt(12345), 0);  // 5

// Get tens place
getDigit(bigInt(12345), 1);  // 4

// Get hundreds place
getDigit(bigInt(12345), 2);  // 3

Byte Array Conversion

/**
 * Convert BigInteger to byte array (base 256)
 */
function toByteArray(num) {
  const array = num.abs().toArray(256);
  return {
    bytes: array.value,
    isNegative: num.isNegative()
  };
}

/**
 * Convert byte array to BigInteger
 */
function fromByteArray(bytes, isNegative = false) {
  const num = bigInt.fromArray(bytes, 256, isNegative);
  return num;
}

// Use
const value = bigInt(123456);
const bytes = toByteArray(value);
// bytes.bytes = [1, 226, 64] (base 256 representation)

const restored = fromByteArray(bytes.bytes, bytes.isNegative);
// restored = 123456

Display Formatting

/**
 * Format BigInteger with thousands separators
 */
function formatWithSeparators(num, separator = ',') {
  const str = num.toString();
  const isNegative = str[0] === '-';
  const digits = isNegative ? str.slice(1) : str;

  const parts = [];
  for (let i = digits.length; i > 0; i -= 3) {
    parts.unshift(digits.slice(Math.max(0, i - 3), i));
  }

  const formatted = parts.join(separator);
  return isNegative ? '-' + formatted : formatted;
}

formatWithSeparators(bigInt("1234567890"));  // "1,234,567,890"
formatWithSeparators(bigInt("-9876543210")); // "-9,876,543,210"

/**
 * Format as hex string with 0x prefix
 */
function toHexString(num) {
  return '0x' + num.toString(16);
}

toHexString(bigInt(255));  // "0xff"

Safe Conversion Check

/**
 * Safely convert to JS number with validation
 */
function toJSNumberSafe(bigInt) {
  const MAX_SAFE = bigInt.constructor(Number.MAX_SAFE_INTEGER);
  const MIN_SAFE = bigInt.constructor(Number.MIN_SAFE_INTEGER);

  if (bigInt.greater(MAX_SAFE) || bigInt.lesser(MIN_SAFE)) {
    throw new Error("Number exceeds safe integer range");
  }

  return bigInt.toJSNumber();
}

// Use
try {
  const safe = toJSNumberSafe(bigInt(1000));  // 1000 (OK)
  const unsafe = toJSNumberSafe(bigInt("9999999999999999"));  // Throws error
} catch (e) {
  console.error("Cannot safely convert to JS number");
}

Performance Notes

  • toString(): O(n²) for arbitrary bases (requires repeated division)
  • toArray(): O(n²) similar to toString
  • toJSNumber(): O(n) - iterates through digits once
  • valueOf(): O(n) - same as toJSNumber
  • toJSON(): O(n²) - calls toString internally

Base conversions are expensive for very large numbers. If you need to repeatedly convert between bases, consider caching the results.

Important Warnings

Precision Loss with JavaScript Numbers

Always be aware of precision loss when converting to JavaScript numbers:

// SAFE: Within range
bigInt(1000000).toJSNumber();  // ✓ Exact

// UNSAFE: Outside safe integer range
bigInt("9007199254740993").toJSNumber();  // ✗ Loses precision

// DANGEROUS: Using valueOf() implicitly
bigInt("99999999999999999") + "";  // ✗ Loses precision, returns "100000000000000000"

// CORRECT: Use toString()
bigInt("99999999999999999").toString();  // ✓ Exact, returns "99999999999999999"

String Conversion Best Practices

  1. Always use toString() or String() explicitly
  2. Never use + "" or other implicit conversions
  3. Use toJSON() for JSON serialization (called automatically)
  4. For display purposes, toString() is your friend
  5. For computation, keep values as BigInteger objects