CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-mathjs

Math.js is an extensive math library for JavaScript and Node.js featuring a flexible expression parser, symbolic computation, and support for numbers, big numbers, complex numbers, fractions, units, and matrices.

84

1.47x
Overview
Eval results
Files

data-types.mddocs/

Data Types and Type System

This document covers Math.js's rich type system, including all built-in data types, type constructors, conversion functions, type checking utilities, and working with the extensible type system that supports numbers, BigNumbers, complex numbers, fractions, units, matrices, and more.

Import

import {
  // Type constructors  
  bignumber, bigint, boolean, complex, fraction, matrix, number, string, unit,
  // Type checking functions
  isNumber, isBigNumber, isBigInt, isComplex, isFraction, isUnit,
  isMatrix, isArray, isString, isBoolean, isNull, isUndefined,
  // Utility functions
  typeOf, clone, format, numeric,
  // Special values
  Infinity, NaN, null, undefined
} from 'mathjs'

Core Numeric Types

JavaScript Numbers

number(value?: MathType, valuelessUnit?: Unit | string): number

{ .api }

// Create numbers
number() // 0
number(5) // 5
number('3.14') // 3.14
number(true) // 1
number(false) // 0

// Convert from other types
number(bignumber('123.456')) // 123.456
number(fraction(3, 4)) // 0.75
number(complex(5, 0)) // 5 (real part, imaginary must be 0)

// With units (extract numeric value)
number(unit('5 m'), 'cm') // 500 (convert to cm, return number)
number(unit('100 fahrenheit'), 'celsius') // ~37.78

// Limitations of JavaScript numbers
number(9007199254740992) // 9007199254740992 (MAX_SAFE_INTEGER + 1)
number(9007199254740993) // 9007199254740992 (precision lost!)

// Special values
number(Infinity) // Infinity
number(-Infinity) // -Infinity  
number(NaN) // NaN

BigNumber (Arbitrary Precision Decimals)

bignumber(value?: MathType): BigNumber

{ .api }

// Create BigNumbers for high precision
bignumber('0.1') // BigNumber(0.1) - exact representation
bignumber('123456789012345678901234567890.123456789') // Full precision

// Avoid precision issues with regular numbers
0.1 + 0.2 // 0.30000000000000004 (JavaScript number)
bignumber('0.1').plus('0.2') // BigNumber(0.3) - exact

// Large integers without precision loss
bignumber('9007199254740993') // Exact (beyond JS safe integer limit)
bignumber('999999999999999999999999999999') // Arbitrary size

// Convert from other types
bignumber(123) // BigNumber(123)
bignumber(fraction(1, 3)) // BigNumber(0.333...) with configured precision
bignumber(3.14159) // BigNumber(3.14159)

// Mathematical operations
const a = bignumber('123.456')
const b = bignumber('789.012')
a.plus(b) // BigNumber(912.468)
a.minus(b) // BigNumber(-665.556)
a.times(b) // BigNumber(97408.265472)
a.div(b) // BigNumber(0.1564...)

// Configuration affects precision
import { create, all } from 'mathjs'
const math = create(all, { precision: 64 }) // 64 significant digits
math.bignumber('1').div('3') // Very high precision result

BigInt (Arbitrary Precision Integers)

bigint(value?: MathType): bigint

{ .api }

// Create BigInts for large integers
bigint(123) // 123n
bigint('9007199254740993') // 9007199254740993n
bigint('999999999999999999999999999999') // Huge integer

// Convert from other types
bigint(bignumber('123')) // 123n
bigint(fraction(10, 2)) // 5n (must be integer fraction)

// BigInt arithmetic (uses JavaScript BigInt operators)
const x = bigint('123456789012345678901234567890')
const y = bigint('987654321098765432109876543210')
// Use standard BigInt operations: +, -, *, /, %, **

// Note: BigInt only supports integers
bigint(3.14) // Error: cannot convert non-integer
bigint(fraction(1, 3)) // Error: fraction is not integer

Complex Numbers

complex(re: MathType, im?: MathType): Complex
complex(value?: MathType): Complex

{ .api }

// Create complex numbers
complex(3, 4) // 3 + 4i
complex(2) // 2 + 0i (real number)
complex() // 0 + 0i

// From string notation
complex('2 + 3i') // 2 + 3i  
complex('5i') // 0 + 5i
complex('-2 - 7i') // -2 - 7i

// From polar form (using Euler's formula)
const r = 5
const theta = pi / 4
complex(multiply(r, cos(theta)), multiply(r, sin(theta))) // 5∠45° in rectangular

// Complex arithmetic
const z1 = complex(1, 2) // 1 + 2i
const z2 = complex(3, -1) // 3 - 1i

add(z1, z2) // Complex(4, 1) = 4 + 1i
subtract(z1, z2) // Complex(-2, 3) = -2 + 3i
multiply(z1, z2) // Complex(5, 5) = 5 + 5i  
divide(z1, z2) // Complex(0.1, 0.7) = 0.1 + 0.7i

// Complex functions
abs(z1) // √5 (magnitude)
arg(z1) // atan2(2, 1) (phase angle)
conj(z1) // Complex(1, -2) = 1 - 2i (conjugate)
re(z1) // 1 (real part)
im(z1) // 2 (imaginary part)

// Complex math functions
sqrt(complex(-1, 0)) // Complex(0, 1) = i
exp(complex(0, pi)) // Complex(-1, 0) ≈ -1 (Euler's identity)
sin(complex(0, 1)) // Complex(0, 1.175...) = i*sinh(1)

Fractions (Exact Rational Numbers)

fraction(numerator: MathType, denominator?: MathType): Fraction
fraction(value?: MathType): Fraction

{ .api }

// Create fractions
fraction(1, 3) // Fraction(1/3)
fraction(22, 7) // Fraction(22/7) ≈ π approximation
fraction(0.5) // Fraction(1/2) - exact conversion
fraction('0.125') // Fraction(1/8)

// Exact arithmetic (no rounding errors)
const third = fraction(1, 3)
const sixth = fraction(1, 6)  
add(third, sixth) // Fraction(1/2) - exact result
multiply(third, 3) // Fraction(1) - exact result

// Avoid decimal precision issues  
fraction(1, 3).toString() // "1/3"
number(fraction(1, 3)) // 0.3333333...

// Fraction operations
const a = fraction(2, 3)
const b = fraction(3, 4)
add(a, b) // Fraction(17/12)
multiply(a, b) // Fraction(1/2)
divide(a, b) // Fraction(8/9)
pow(a, 2) // Fraction(4/9)

// Convert decimals to fractions
fraction(0.75) // Fraction(3/4)
fraction(0.333333) // Fraction(1/3) - recognizes pattern
fraction(0.142857142857) // Fraction(1/7) - recognizes repeating decimal

// Mixed numbers and improper fractions  
const improper = fraction(7, 3) // 7/3 = 2⅓
improper.valueOf() // 2.333...

Composite Types

Units (Quantities with Dimensions)

unit(value?: string | number, unit?: string): Unit

{ .api }

// Create units (see units.md for comprehensive coverage)
unit('5 meter') // 5 meter
unit(10, 'cm') // 10 cm
unit('25 celsius') // 25 celsius

// Units with different numeric types  
unit(bignumber('3.14159'), 'radian') // High-precision angle
unit(complex(1, 1), 'meter') // Complex-valued length
unit(fraction(1, 2), 'hour') // Exact time fraction

// Compound units
unit('60 km/h') // Speed
unit('9.8 m/s^2') // Acceleration  
unit('100 J/(mol*K)') // Specific heat capacity

// Unit conversion preserves numeric type
const bigDistance = unit(bignumber('1000.123456789'), 'meter')  
to(bigDistance, 'km') // BigNumber result: 1.000123456789 km

Matrices and Arrays

matrix(data: MathArray | Matrix, format?: 'dense' | 'sparse', dataType?: string): Matrix

{ .api }

// Create matrices from arrays
matrix([[1, 2], [3, 4]]) // 2×2 dense matrix
matrix([1, 2, 3, 4]) // Column vector (4×1)

// Specify format and data type
matrix([[1, 0, 0], [0, 2, 0], [0, 0, 3]], 'sparse') // Sparse matrix
matrix([[1, 2], [3, 4]], 'dense', 'number') // Explicit number type

// Mixed-type matrices
matrix([
  [1, bignumber('2.5')],
  [fraction(3, 4), complex(1, 2)]
]) // Each element can have different numeric type

// Specialized matrices
identity(3) // 3×3 identity matrix
zeros([2, 3]) // 2×3 zero matrix  
ones([3, 2]) // 3×2 matrix of ones
range(0, 10, 2) // [0, 2, 4, 6, 8] as matrix

// Matrix properties
const A = matrix([[1, 2, 3], [4, 5, 6]])
size(A) // [2, 3] - dimensions
A.storage() // 'dense' - storage format  
A.datatype() // 'number' - element data type

Strings

string(value?: MathType): string

{ .api }

// Convert values to strings
string(123) // '123'  
string(bignumber('123.456')) // '123.456'
string(complex(2, 3)) // '2 + 3i'
string(fraction(1, 3)) // '1/3'
string(unit('5 meter')) // '5 meter'
string([[1, 2], [3, 4]]) // '[[1, 2], [3, 4]]'

// Format control (see format function for advanced options)
format(bignumber('123.456789'), { precision: 3 }) // '123'
format(complex(1, 2), { notation: 'exponential' }) // '1e+0 + 2e+0i'

Booleans

boolean(value?: MathType): boolean

{ .api }

// Convert to boolean
boolean(1) // true
boolean(0) // false
boolean('true') // true
boolean('false') // false
boolean('') // false
boolean('hello') // true (non-empty string)

// Numeric conversions  
boolean(bignumber('0')) // false
boolean(bignumber('1')) // true
boolean(complex(0, 0)) // false
boolean(complex(1, 0)) // true

// Special values
boolean(null) // false
boolean(undefined) // false
boolean(NaN) // false
boolean(Infinity) // true

Type Checking Functions

Basic Type Checks

// Number type checks
isNumber(x: any): boolean
isBigNumber(x: any): boolean  
isBigInt(x: any): boolean
isNumeric(x: any): boolean

{ .api }

// Check specific numeric types
isNumber(5) // true
isNumber('5') // false
isBigNumber(bignumber('5')) // true
isBigInt(5n) // true
isNumeric(5) // true  
isNumeric(bignumber('5')) // true
isNumeric('5') // false

// Value checking
isInteger(5) // true
isInteger(5.5) // false
isNaN(NaN) // true
isNaN(5) // false
isZero(0) // true  
isZero(bignumber('0')) // true
isPositive(5) // true
isNegative(-3) // true

Complex Type Checks

// Complex and composite types
isComplex(x: any): boolean
isFraction(x: any): boolean
isUnit(x: any): boolean
isMatrix(x: any): boolean
isArray(x: any): boolean

{ .api }

isComplex(complex(1, 2)) // true
isComplex(5) // false (real numbers are not complex objects)
isFraction(fraction(1, 2)) // true  
isUnit(unit('5 m')) // true
isMatrix(matrix([[1, 2]])) // true
isArray([1, 2, 3]) // true
isArray(matrix([1, 2, 3])) // false (matrix is not array)

// Matrix type specifics
isDenseMatrix(matrix([[1, 2]])) // true
isSparseMatrix(sparse([[1, 0]])) // true

Collection and Structure Checks

isCollection(x: any): boolean // Matrix or Array
isRange(x: any): boolean
isIndex(x: any): boolean  
isResultSet(x: any): boolean

{ .api }

isCollection([1, 2, 3]) // true
isCollection(matrix([1, 2, 3])) // true  
isCollection(5) // false

isRange(range(0, 10)) // true
isIndex(index(0, 1)) // true

General Type Checks

isString(x: any): boolean
isBoolean(x: any): boolean
isFunction(x: any): boolean
isDate(x: any): boolean
isRegExp(x: any): boolean
isObject(x: any): boolean
isNull(x: any): boolean
isUndefined(x: any): boolean

{ .api }

isString('hello') // true
isBoolean(true) // true
isFunction(sin) // true
isDate(new Date()) // true
isRegExp(/pattern/) // true
isObject({a: 1}) // true  
isNull(null) // true
isUndefined(undefined) // true

AST Node Type Checks

// Check AST node types (for expression parsing)
isNode(x: any): boolean
isSymbolNode(x: any): boolean
isConstantNode(x: any): boolean
isFunctionNode(x: any): boolean
isOperatorNode(x: any): boolean
// ... and many more node type checks

{ .api }

const node = parse('x + 1')
isNode(node) // true
isOperatorNode(node) // true (+ operator)
isSymbolNode(node.args[0]) // true (x symbol)
isConstantNode(node.args[1]) // true (1 constant)

Type Conversion and Utilities

Generic Type Information

typeOf(x: any): string

{ .api }

// Get type name
typeOf(5) // 'number'
typeOf(bignumber('5')) // 'BigNumber'  
typeOf(complex(1, 2)) // 'Complex'
typeOf(fraction(1, 2)) // 'Fraction'
typeOf(unit('5 m')) // 'Unit'
typeOf(matrix([1, 2])) // 'Matrix'
typeOf([1, 2, 3]) // 'Array'
typeOf('hello') // 'string'
typeOf(true) // 'boolean'
typeOf(null) // 'null'
typeOf(undefined) // 'undefined'

// Use for runtime type dispatch
function processValue(x) {
  switch (typeOf(x)) {
    case 'number': return x * 2
    case 'BigNumber': return x.times(2)
    case 'Complex': return multiply(x, 2)
    case 'string': return x + x
    default: throw new Error(`Unsupported type: ${typeOf(x)}`)
  }
}

Deep Cloning

clone(x: any): any

{ .api }

// Deep clone objects and values
const original = {
  num: 5,
  big: bignumber('123.456'),
  matrix: matrix([[1, 2], [3, 4]]),
  nested: { a: 1, b: [2, 3] }
}

const copy = clone(original)
copy.matrix.set([0, 0], 99) // Modifying copy doesn't affect original

// Clone preserves types
typeOf(clone(bignumber('5'))) // 'BigNumber'
typeOf(clone(complex(1, 2))) // 'Complex'

Numeric Type Conversion

numeric(value: MathType, outputType: string): MathType

{ .api }

// Convert between numeric types
numeric(5, 'BigNumber') // BigNumber(5)
numeric('3.14', 'number') // 3.14
numeric(bignumber('123'), 'bigint') // 123n
numeric(fraction(1, 2), 'number') // 0.5

// Preserve precision when possible
numeric(bignumber('123.456789'), 'Fraction') // Fraction representing exact decimal
numeric('0.1', 'BigNumber') // BigNumber(0.1) - no precision loss

Advanced Type System Features

Configurable Default Types

// Configure Math.js to use different default types
import { create, all } from 'mathjs'

// Use BigNumbers by default
const mathBig = create(all, {
  number: 'BigNumber',
  precision: 64
})

mathBig.evaluate('0.1 + 0.2') // BigNumber(0.3) - exact
mathBig.add(0.1, 0.2) // BigNumber(0.3)

// Use fractions by default  
const mathFrac = create(all, {
  number: 'Fraction'
})

mathFrac.evaluate('1/3 + 1/6') // Fraction(1/2) - exact

Type Coercion Rules

// Math.js follows specific type coercion rules:

// 1. Operations preserve the "highest" precision type
add(5, bignumber('2')) // BigNumber(7) - bignumber wins
multiply(fraction(1, 2), 3) // Fraction(3/2) - fraction wins
add(2, complex(3, 4)) // Complex(5, 4) - complex wins

// 2. Unit operations require compatible dimensions
add(unit('5 m'), unit('3 ft')) // 5.9144 meter (auto-conversion)
multiply(unit('5 m'), unit('3 s')) // 15 m*s (compound unit)

// 3. Matrix operations work element-wise with type promotion
const A = matrix([[1, 2]])
const B = matrix([[bignumber('3'), bignumber('4')]])
add(A, B) // Matrix with BigNumber elements

Custom Type Extensions

// Extend Math.js with custom types (advanced)
import { create, factory } from 'mathjs'

// Example: Custom Rational type (simplified)
class Rational {
  constructor(num, den = 1) {
    this.num = num
    this.den = den
  }
  
  toString() {
    return `${this.num}/${this.den}`
  }
}

// Create factory for custom type
const createRational = factory('rational', [], () => {
  return function rational(num, den) {
    return new Rational(num, den)
  }
})

// Register with Math.js
const math = create({
  createRational,
  // ... other dependencies
})

Type Validation and Error Handling

Input Validation

function validateNumeric(value, allowedTypes = ['number', 'BigNumber']) {
  const type = typeOf(value)
  if (!allowedTypes.includes(type)) {
    throw new TypeError(`Expected ${allowedTypes.join(' or ')}, got ${type}`)
  }
  return value
}

function safeConvert(value, targetType) {
  try {
    return numeric(value, targetType)
  } catch (error) {
    console.warn(`Cannot convert ${typeOf(value)} to ${targetType}`)
    return value // Return original on failure
  }
}

Type-Safe Operations

// Ensure compatible types for operations
function safeAdd(a, b) {
  // Convert to common type if possible
  if (typeOf(a) !== typeOf(b)) {
    try {
      if (isNumber(a) && isBigNumber(b)) {
        a = bignumber(a)
      } else if (isBigNumber(a) && isNumber(b)) {
        b = bignumber(b)  
      }
    } catch (error) {
      throw new TypeError(`Cannot add ${typeOf(a)} and ${typeOf(b)}`)
    }
  }
  
  return add(a, b)
}

// Type guards for specific operations
function requiresInteger(value) {
  if (!isInteger(value)) {
    throw new TypeError(`Expected integer, got ${typeOf(value)}`)
  }
}

function requiresReal(value) {
  if (isComplex(value) && im(value) !== 0) {
    throw new TypeError('Complex numbers with non-zero imaginary part not allowed')
  }
}

Performance Considerations

Type Selection for Performance

// Performance hierarchy (fastest to slowest):
// 1. JavaScript number - fastest for small numbers
// 2. BigInt - fast for large integers  
// 3. Complex - overhead for real/imaginary parts
// 4. BigNumber - arbitrary precision overhead
// 5. Fraction - rational arithmetic overhead
// 6. Unit - dimension checking overhead

// Choose appropriate type for your use case:
const fastCalc = 5 + 3 // JavaScript number: fastest
const preciseCalc = bignumber('5').plus('3') // BigNumber: precise  
const integerCalc = 5n + 3n // BigInt: large integers
const exactCalc = add(fraction(1,3), fraction(1,6)) // Fraction: exact rationals

Memory Usage

// Memory usage considerations:
const numbers = Array(1000000).fill().map((_, i) => i) // ~8MB (numbers)
const bigNumbers = numbers.map(bignumber) // ~40MB+ (BigNumbers)  
const complexNumbers = numbers.map(x => complex(x, 0)) // ~24MB+ (Complex)

// Use appropriate precision
const math64 = create(all, { precision: 64 }) // High precision
const math16 = create(all, { precision: 16 }) // Lower precision, less memory

Type Conversion Costs

// Minimize unnecessary conversions
const big1 = bignumber('123')
const big2 = bignumber('456')

// Efficient: stay in same type
const result1 = big1.plus(big2) // Fast BigNumber operation

// Inefficient: multiple conversions  
const result2 = add(number(big1), number(big2)) // Convert to number, lose precision
const result3 = bignumber(result2) // Convert back to BigNumber

// Better: use Math.js functions that preserve types
const result4 = add(big1, big2) // Automatic type handling

Common Type Patterns

Working with Mixed-Type Data

// Normalize array to common type
function normalizeToType(array, targetType) {
  return array.map(x => numeric(x, targetType))
}

const mixedData = [1, bignumber('2'), fraction(3, 1), '4']
const normalized = normalizeToType(mixedData, 'BigNumber')
// All BigNumber elements

// Find "highest" type in array
function getHighestType(array) {
  const typeHierarchy = ['number', 'BigNumber', 'Fraction', 'Complex']
  let highest = 'number'
  
  array.forEach(value => {
    const valueType = typeOf(value)
    if (typeHierarchy.indexOf(valueType) > typeHierarchy.indexOf(highest)) {
      highest = valueType
    }
  })
  
  return highest
}

Type-Preserving Operations

// Ensure operations preserve input type characteristics
function preservingAdd(a, b) {
  const resultType = typeOf(a) === typeOf(b) ? typeOf(a) : 'number'
  const result = add(a, b)
  
  // Convert result back to expected type if needed
  if (typeOf(result) !== resultType) {
    return numeric(result, resultType)
  }
  
  return result
}

// Batch operations with type consistency
function sumArray(array) {
  if (array.length === 0) return 0
  
  const firstType = typeOf(array[0])
  return array.reduce((sum, value) => {
    // Ensure all values are same type as first
    const normalizedValue = typeOf(value) === firstType ? 
      value : numeric(value, firstType)
    return add(sum, normalizedValue)
  })
}

Chain Operations with Types

// Type information is preserved through chain operations
const result = chain(bignumber('123.456'))
  .add(bignumber('0.544'))  // BigNumber arithmetic
  .multiply(2)              // Mixed operation  
  .divide(bignumber('3'))   // Back to BigNumber
  .done()                   // Result is BigNumber

typeOf(result) // 'BigNumber'

// Unit chains preserve dimensions
const physics = chain(unit('10 m'))
  .multiply(unit('5 m'))    // 50 m^2  
  .divide(unit('2 s'))      // 25 m^2/s
  .multiply(unit('3 s'))    // 75 m^2
  .done()

unit.dimensions // Area (length^2)

Install with Tessl CLI

npx tessl i tessl/npm-mathjs

docs

arithmetic.md

data-types.md

expressions.md

index.md

matrices.md

probability.md

statistics.md

trigonometry.md

units.md

tile.json