DecimalThe 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
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'
new Decimal(value)Create a new arbitrary precision decimal.
Syntaxnew Decimal(decimal) // Clone existing new Decimal(string) // Parse from string new Decimal(number | bigint) // From number new Decimal([int, frac, scale]) // From tuple
| Parameter | Type | Description |
|---|---|---|
value required | Decimal | string | number | bigint | [bigint, bigint, number] | Value to create decimal from. |
// 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);
Decimal.parse(string)Parse a decimal from a string.
SyntaxDecimal.parse(str)
Decimal - Parsed decimal
const price = Decimal.parse('19.99'); const percentage = Decimal.parse('0.075'); // 7.5%
.toString()Convert to string representation (preserves precision).
Syntaxdecimal.toString()
string - String representation
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.
Syntaxdecimal.toNumber()
number - JavaScript number (may lose precision)
WarningConverting to number may lose precision for very large or very precise values.
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.
Syntaxdecimal.toJSON()
string - String representation for JSON
.plus(other)Add another decimal.
Syntaxdecimal.plus(other)
| Parameter | Type | Description |
|---|---|---|
other required | Decimal | string | number | Value to add. |
Decimal - Sum
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.
Syntaxdecimal.minus(other)
Decimal - Difference
.times(other)Multiply by another decimal.
Syntaxdecimal.times(other)
Decimal - Product
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.
Syntaxdecimal.dividedBy(other)
Decimal - Quotient
.equals(other)Check if two decimals are equal.
Syntaxdecimal.equals(other)
boolean - True if equal
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
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'
// 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}`);
// 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());
// 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());
// 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'
// 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());
// 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
// 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
// Good: String preserves precision const display = price.toString(); console.log(`$${display}`); // Avoid: Number may lose precision const display = price.toNumber().toFixed(2);
// 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 });
// 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
// Problem: Loses precision const result = price.toNumber() + tax.toNumber(); // Solution: Keep as Decimal const result = price.plus(tax);