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.add(b).toString()); // '0.3'Constructor
new Decimal(value)
Create a new arbitrary precision decimal.
new Decimal(decimal) // Clone existing
new Decimal(string) // Parse from string
new Decimal(number | bigint) // From number
new Decimal([int, frac, scale]) // From tupleParameters
Parameter | Type | Description |
|---|---|---|
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.fromScientificNotation(input)
Parse a decimal from scientific notation string.
Decimal.fromScientificNotation(input)Parameters
Parameter | Type | Description |
|---|---|---|
input | string | Scientific notation string to parse. |
Returns
Decimal - Parsed decimal
Example
const value = Decimal.fromScientificNotation('1.23e10');
const small = Decimal.fromScientificNotation('5.67e-8');Properties
.int
The integer part of the decimal as a bigint.
const d = new Decimal('19.99');
console.log(d.int); // 19n .frac
The fractional part of the decimal as a bigint.
const d = new Decimal('19.99');
console.log(d.frac); // 99n .scale
The number of decimal places.
const d = new Decimal('19.99');
console.log(d.scale); // 2Instance methods
.toString()
Convert to string representation (preserves precision).
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 .toFloat()
Convert to JavaScript number.
decimal.toFloat()Returns
number - JavaScript number (may lose precision)
Converting to number may lose precision for very large or very precise values.
Example
const price = new Decimal('19.99');
const num = price.toFloat(); // 19.99
// Precision loss example
const precise = new Decimal('0.123456789012345678901234567890');
const lost = precise.toFloat(); // Precision beyond ~15 digits is lost .toJSON()
Serialize for JSON.
decimal.toJSON()Returns
string - String representation for JSON
.toBigInt()
Truncate to a bigint, discarding the fractional part.
decimal.toBigInt()Returns
bigint - Integer part of the decimal
Example
const d = new Decimal('19.99');
console.log(d.toBigInt()); // 19n .toFixed(precision)
Format the decimal with a fixed number of decimal places.
decimal.toFixed(precision)Parameters
Parameter | Type | Description |
|---|---|---|
precision | number | Number of decimal places. |
Returns
string - Fixed-point notation string
Example
const d = new Decimal('19.9');
console.log(d.toFixed(4)); // '19.9000' .toScientific()
Convert to scientific notation string.
decimal.toScientific()Returns
string - Scientific notation representation
Example
const d = new Decimal('12300');
console.log(d.toScientific()); // e.g. '1.23e4' .toParts()
Decompose the decimal into its constituent parts.
decimal.toParts()Returns
{ int: bigint, frac: bigint, scale: number } - The integer part, fractional part, and scale
Example
const d = new Decimal('19.99');
const parts = d.toParts();
// { int: 19n, frac: 99n, scale: 2 } .add(other)
Add another decimal.
decimal.add(other)Parameters
Parameter | Type | Description |
|---|---|---|
other | Decimal | Value to add. |
Returns
Decimal - Sum
Example
const price1 = new Decimal('19.99');
const price2 = new Decimal('5.50');
const total = price1.add(price2);
console.log(total.toString()); // '25.49' .sub(other)
Subtract another decimal.
decimal.sub(other)Parameters
Parameter | Type | Description |
|---|---|---|
other | Decimal | Value to subtract. |
Returns
Decimal - Difference
.mul(other)
Multiply by another decimal.
decimal.mul(other)Parameters
Parameter | Type | Description |
|---|---|---|
other | Decimal | Value to multiply by. |
Returns
Decimal - Product
Example
const price = new Decimal('19.99');
const quantity = new Decimal('3');
const total = price.mul(quantity);
console.log(total.toString()); // '59.97' .div(other)
Divide by another decimal.
decimal.div(other)Parameters
Parameter | Type | Description |
|---|---|---|
other | Decimal | Value to divide by. |
Returns
Decimal - Quotient
.mod(other)
Calculate the remainder after division.
decimal.mod(other)Parameters
Parameter | Type | Description |
|---|---|---|
other | Decimal | Divisor. |
Returns
Decimal - Remainder
Example
const d = new Decimal('10');
const remainder = d.mod(new Decimal('3'));
console.log(remainder.toString()); // '1' .abs()
Get the absolute value.
decimal.abs()Returns
Decimal - Absolute value
Example
const d = new Decimal('-19.99');
console.log(d.abs().toString()); // '19.99' .neg()
Negate the decimal.
decimal.neg()Returns
Decimal - Negated value
Example
const d = new Decimal('19.99');
console.log(d.neg().toString()); // '-19.99' .round(precision)
Round to a given number of decimal places.
decimal.round(precision)Parameters
Parameter | Type | Description |
|---|---|---|
precision | number | Number of decimal places to round to. |
Returns
Decimal - Rounded value
Example
const d = new Decimal('19.995');
console.log(d.round(2).toString()); // '20.00' .equals(other)
Check if two decimals are equal.
decimal.equals(other)Returns
boolean - True if equal
.compare(other)
Compare two decimals.
decimal.compare(other)Parameters
Parameter | Type | Description |
|---|---|---|
other | Decimal | Decimal to compare against. |
Returns
number - Returns -1 if less than, 0 if equal, 1 if greater than
Example
const a = new Decimal('10');
const b = new Decimal('20');
console.log(a.compare(b)); // -1
console.log(b.compare(a)); // 1
console.log(a.compare(a)); // 0 .isZero()
Check if the decimal is zero.
decimal.isZero()Returns
boolean - True if the value is zero
Example
const zero = new Decimal('0');
console.log(zero.isZero()); // true
const nonZero = new Decimal('1');
console.log(nonZero.isZero()); // false .isNegative()
Check if the decimal is negative.
decimal.isNegative()Returns
boolean - True if the value is negative
Example
const neg = new Decimal('-5');
console.log(neg.isNegative()); // true
const pos = new Decimal('5');
console.log(pos.isNegative()); // falseComplete 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.mul(taxRate);
const total = price.add(tax);
console.log('Price:', price.toString()); // 19.99
console.log('Tax:', tax.toString()); // 1.49925
console.log('Total:', total.toString()); // 21.48925Order 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.mul(new Decimal(item.quantity));
total = total.add(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.mul(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').add(rate);
for (let i = 0; i < periods; i++) {
amount = amount.mul(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.add(txn.amount);
}
console.log('Total:', totalAmount.toString());Percentage calculations
// Calculate percentage
function calculatePercentage(value: Decimal, percentage: Decimal): Decimal {
return value.mul(percentage).div(new Decimal('100'));
}
const price = new Decimal('100.00');
const discount = new Decimal('15'); // 15%
const discountAmount = calculatePercentage(price, discount);
const finalPrice = price.sub(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 imprecision2. Keep as Decimal for calculations
// Good: All calculations use Decimal
const subtotal = price.mul(quantity);
const tax = subtotal.mul(taxRate);
const total = subtotal.add(tax);
// Avoid: Converting to number mid-calculation
const subtotal = price.toFloat() * quantity; // Loses precision3. Convert to string for display
// Good: String preserves precision
const display = price.toString();
console.log(`$${display}`);
// Avoid: Number may lose precision
const display = price.toFloat().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').add(new Decimal('0.2')); // 0.3Premature conversion to number
// Problem: Loses precision
const result = price.toFloat() + tax.toFloat();
// Solution: Keep as Decimal
const result = price.add(tax);See also
Data types overview - All custom data types
Query builders - Using Decimal in queries
SurrealQL decimal - Database decimal type