Decimal

The Decimal class provides arbitrary precision decimal numbers, essential for financial calculations and applications where floating-point precision errors are unacceptable.

Import:

import { Decimal } from 'surrealdb';

Source: value/decimal.ts

Why Use Decimal?

JavaScript's number type uses floating-point arithmetic, which can lead to precision errors:

// Floating-point precision error
console.log(0.1 + 0.2); // 0.30000000000000004

// Decimal preserves precision
const a = new Decimal('0.1');
const b = new Decimal('0.2');
console.log(a.plus(b).toString()); // '0.3'

Constructor

new Decimal(value)

Create a new arbitrary precision decimal.

Syntax

new Decimal(decimal) // Clone existing
new Decimal(string) // Parse from string
new Decimal(number | bigint) // From number
new Decimal([int, frac, scale]) // From tuple

Parameters

ParameterTypeDescription
value Decimal | string | number | bigint | [bigint, bigint, number]Value to create decimal from.

Examples

// From string (recommended for precision)
const price = new Decimal('19.99');
const precise = new Decimal('0.123456789012345678901234567890');

// From number (may have floating-point precision)
const value = new Decimal(19.99);

// From bigint
const large = new Decimal(1000000n);

// Scientific notation
const scientific = new Decimal('1.23e-10');

// Clone existing
const copy = new Decimal(price);

Static Methods

Decimal.parse(string)

Parse a decimal from a string.

Syntax

Decimal.parse(str)

Returns

Decimal - Parsed decimal

Example

const price = Decimal.parse('19.99');
const percentage = Decimal.parse('0.075'); // 7.5%

Instance Methods

.toString()

Convert to string representation (preserves precision).

Syntax

decimal.toString()

Returns

string - String representation

Example

const price = new Decimal('19.99');
console.log(price.toString()); // '19.99'

const precise = new Decimal('0.123456789012345678901234567890');
console.log(precise.toString()); // Full precision preserved

.toNumber()

Convert to JavaScript number.

Syntax

decimal.toNumber()

Returns

number - JavaScript number (may lose precision)

Example

const price = new Decimal('19.99');
const num = price.toNumber(); // 19.99

// Precision loss example
const precise = new Decimal('0.123456789012345678901234567890');
const lost = precise.toNumber(); // Precision beyond ~15 digits is lost

.toJSON()

Serialize for JSON.

Syntax

decimal.toJSON()

Returns

string - String representation for JSON

.plus(other)

Add another decimal.

Syntax

decimal.plus(other)

Parameters

ParameterTypeDescription
other Decimal | string | numberValue to add.

Returns

Decimal - Sum

Example

const price1 = new Decimal('19.99');
const price2 = new Decimal('5.50');
const total = price1.plus(price2);
console.log(total.toString()); // '25.49'

.minus(other)

Subtract another decimal.

Syntax

decimal.minus(other)

Returns

Decimal - Difference

.times(other)

Multiply by another decimal.

Syntax

decimal.times(other)

Returns

Decimal - Product

Example

const price = new Decimal('19.99');
const quantity = new Decimal('3');
const total = price.times(quantity);
console.log(total.toString()); // '59.97'

.dividedBy(other)

Divide by another decimal.

Syntax

decimal.dividedBy(other)

Returns

Decimal - Quotient

.equals(other)

Check if two decimals are equal.

Syntax

decimal.equals(other)

Returns

boolean - True if equal

Complete Examples

Financial Calculations

import { Surreal, Decimal, Table } from 'surrealdb';

const db = new Surreal();
await db.connect('ws://localhost:8000');

// Product prices
const product = await db.create(new Table('products')).content({
name: 'Widget',
price: new Decimal('19.99'),
tax_rate: new Decimal('0.075') // 7.5%
});

// Calculate total with tax
const price = new Decimal(product.price);
const taxRate = new Decimal(product.tax_rate);
const tax = price.times(taxRate);
const total = price.plus(tax);

console.log('Price:', price.toString()); // 19.99
console.log('Tax:', tax.toString()); // 1.49925
console.log('Total:', total.toString()); // 21.48925

Order Total Calculation

interface OrderItem {
product: string;
price: Decimal;
quantity: number;
}

function calculateOrderTotal(items: OrderItem[]): Decimal {
let total = new Decimal('0');

for (const item of items) {
const itemTotal = item.price.times(item.quantity);
total = total.plus(itemTotal);
}

return total;
}

const items = [
{ product: 'Widget', price: new Decimal('19.99'), quantity: 2 },
{ product: 'Gadget', price: new Decimal('29.99'), quantity: 1 },
{ product: 'Tool', price: new Decimal('9.99'), quantity: 3 }
];

const orderTotal = calculateOrderTotal(items);
console.log('Order total:', orderTotal.toString()); // '99.94'

Currency Exchange

// Exchange rate calculation
const usdAmount = new Decimal('100.00');
const exchangeRate = new Decimal('1.18'); // USD to EUR

const eurAmount = usdAmount.times(exchangeRate);
console.log(`$${usdAmount} = €${eurAmount}`);

Interest Calculation

// Calculate compound interest
function calculateCompoundInterest(
principal: Decimal,
rate: Decimal,
periods: number
): Decimal {
let amount = principal;
const onePlusRate = new Decimal('1').plus(rate);

for (let i = 0; i < periods; i++) {
amount = amount.times(onePlusRate);
}

return amount;
}

const principal = new Decimal('1000.00');
const annualRate = new Decimal('0.05'); // 5%
const years = 10;

const finalAmount = calculateCompoundInterest(principal, annualRate, years);
console.log('Final amount:', finalAmount.toString());

Database Storage

// Store precise financial data
const transaction = await db.create(new Table('transactions')).content({
user: userId,
amount: new Decimal('149.99'),
fee: new Decimal('2.50'),
tax: new Decimal('11.25'),
timestamp: DateTime.now()
});

// Query and calculate
const transactions = await db.select(new Table('transactions'));
let totalAmount = new Decimal('0');

for (const txn of transactions) {
totalAmount = totalAmount.plus(txn.amount);
}

console.log('Total:', totalAmount.toString());

Percentage Calculations

// Calculate percentage
function calculatePercentage(value: Decimal, percentage: Decimal): Decimal {
return value.times(percentage).dividedBy(new Decimal('100'));
}

const price = new Decimal('100.00');
const discount = new Decimal('15'); // 15%

const discountAmount = calculatePercentage(price, discount);
const finalPrice = price.minus(discountAmount);

console.log('Discount:', discountAmount.toString()); // '15.00'
console.log('Final price:', finalPrice.toString()); // '85.00'

Scientific Calculations

// High precision scientific value
const avogadroNumber = new Decimal('6.02214076e23');
const boltzmannConstant = new Decimal('1.380649e-23');

console.log('Avogadro:', avogadroNumber.toString());
console.log('Boltzmann:', boltzmannConstant.toString());

Best Practices

1. Use Strings for Input

// Good: String input preserves precision
const price = new Decimal('19.99');

// Caution: Number input may have floating-point errors
const price = new Decimal(19.99); // Already has float imprecision

2. Keep as Decimal for Calculations

// Good: All calculations use Decimal
const subtotal = price.times(quantity);
const tax = subtotal.times(taxRate);
const total = subtotal.plus(tax);

// Avoid: Converting to number mid-calculation
const subtotal = price.toNumber() * quantity; // Loses precision

3. Convert to String for Display

// Good: String preserves precision
const display = price.toString();
console.log(`$${display}`);

// Avoid: Number may lose precision
const display = price.toNumber().toFixed(2);

4. Store Decimals in Database

// Good: Store as Decimal
await db.create(table).content({
price: new Decimal('19.99')
});

// Avoid: Store as number
await db.create(table).content({
price: 19.99 // Float imprecision
});

Common Pitfalls

Floating-Point Input

// Problem: Number already has floating-point error
const wrong = new Decimal(0.1 + 0.2); // 0.30000000000000004

// Solution: Use string input
const correct = new Decimal('0.1').plus(new Decimal('0.2')); // 0.3

Premature Conversion to Number

// Problem: Loses precision
const result = price.toNumber() + tax.toNumber();

// Solution: Keep as Decimal
const result = price.plus(tax);

See Also