# Decimal

Arbitrary precision decimal numbers for financial and scientific calculations.

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

**Import:**
```ts
import { Decimal } from 'surrealdb';
```

**Source:** [value/decimal.ts](https://github.com/surrealdb/surrealdb.js/blob/main/packages/sdk/src/value/decimal.ts)

## Why use Decimal?

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

```ts
// 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)` {#constructor}

Create a new arbitrary precision decimal.

```ts title="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
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>value</code> <label label="required" /></td>
            <td><code>Decimal | string | number | bigint | [bigint, bigint, number]</code></td>
            <td>Value to create decimal from.</td>
        </tr>
    </tbody>
</table>

#### Examples

```ts
// 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)` {#fromscientificnotation}

Parse a decimal from scientific notation string.

```ts title="Syntax"
Decimal.fromScientificNotation(input)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>input</code> <label label="required" /></td>
            <td><code>string</code></td>
            <td>Scientific notation string to parse.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Parsed decimal

#### Example

```ts
const value = Decimal.fromScientificNotation('1.23e10');
const small = Decimal.fromScientificNotation('5.67e-8');
```

## Properties

### `.int` {#int}

The integer part of the decimal as a `bigint`.

```ts
const d = new Decimal('19.99');
console.log(d.int); // 19n
```

---

### `.frac` {#frac}

The fractional part of the decimal as a `bigint`.

```ts
const d = new Decimal('19.99');
console.log(d.frac); // 99n
```

---

### `.scale` {#scale}

The number of decimal places.

```ts
const d = new Decimal('19.99');
console.log(d.scale); // 2
```

## Instance methods

### `.toString()` {#tostring}

Convert to string representation (preserves precision).

```ts title="Syntax"
decimal.toString()
```

#### Returns
`string` - String representation

#### Example

```ts
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()` {#tofloat}

Convert to JavaScript number.

```ts title="Syntax"
decimal.toFloat()
```

#### Returns
`number` - JavaScript number (may lose precision)

> [!WARNING]
> Converting to number may lose precision for very large or very precise values.

#### Example

```ts
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()` {#tojson}

Serialise for JSON.

```ts title="Syntax"
decimal.toJSON()
```

#### Returns
`string` - String representation for JSON

---

### `.toBigInt()` {#tobigint}

Truncate to a `bigint`, discarding the fractional part.

```ts title="Syntax"
decimal.toBigInt()
```

#### Returns
`bigint` - Integer part of the decimal

#### Example

```ts
const d = new Decimal('19.99');
console.log(d.toBigInt()); // 19n
```

---

### `.toFixed(precision)` {#tofixed}

Format the decimal with a fixed number of decimal places.

```ts title="Syntax"
decimal.toFixed(precision)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>precision</code> <label label="required" /></td>
            <td><code>number</code></td>
            <td>Number of decimal places.</td>
        </tr>
    </tbody>
</table>

#### Returns
`string` - Fixed-point notation string

#### Example

```ts
const d = new Decimal('19.9');
console.log(d.toFixed(4)); // '19.9000'
```

---

### `.toScientific()` {#toscientific}

Convert to scientific notation string.

```ts title="Syntax"
decimal.toScientific()
```

#### Returns
`string` - Scientific notation representation

#### Example

```ts
const d = new Decimal('12300');
console.log(d.toScientific()); // e.g. '1.23e4'
```

---

### `.toParts()` {#toparts}

Decompose the decimal into its constituent parts.

```ts title="Syntax"
decimal.toParts()
```

#### Returns
`{ int: bigint, frac: bigint, scale: number }` - The integer part, fractional part, and scale

#### Example

```ts
const d = new Decimal('19.99');
const parts = d.toParts();
// { int: 19n, frac: 99n, scale: 2 }
```

---

### `.add(other)` {#add}

Add another decimal.

```ts title="Syntax"
decimal.add(other)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>other</code> <label label="required" /></td>
            <td><code>Decimal</code></td>
            <td>Value to add.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Sum

#### Example

```ts
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)` {#sub}

Subtract another decimal.

```ts title="Syntax"
decimal.sub(other)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>other</code> <label label="required" /></td>
            <td><code>Decimal</code></td>
            <td>Value to subtract.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Difference

---

### `.mul(other)` {#mul}

Multiply by another decimal.

```ts title="Syntax"
decimal.mul(other)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>other</code> <label label="required" /></td>
            <td><code>Decimal</code></td>
            <td>Value to multiply by.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Product

#### Example

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

---

### `.div(other)` {#div}

Divide by another decimal.

```ts title="Syntax"
decimal.div(other)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>other</code> <label label="required" /></td>
            <td><code>Decimal</code></td>
            <td>Value to divide by.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Quotient

---

### `.mod(other)` {#mod}

Calculate the remainder after division.

```ts title="Syntax"
decimal.mod(other)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>other</code> <label label="required" /></td>
            <td><code>Decimal</code></td>
            <td>Divisor.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Remainder

#### Example

```ts
const d = new Decimal('10');
const remainder = d.mod(new Decimal('3'));
console.log(remainder.toString()); // '1'
```

---

### `.abs()` {#abs}

Get the absolute value.

```ts title="Syntax"
decimal.abs()
```

#### Returns
`Decimal` - Absolute value

#### Example

```ts
const d = new Decimal('-19.99');
console.log(d.abs().toString()); // '19.99'
```

---

### `.neg()` {#neg}

Negate the decimal.

```ts title="Syntax"
decimal.neg()
```

#### Returns
`Decimal` - Negated value

#### Example

```ts
const d = new Decimal('19.99');
console.log(d.neg().toString()); // '-19.99'
```

---

### `.round(precision)` {#round}

Round to a given number of decimal places.

```ts title="Syntax"
decimal.round(precision)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>precision</code> <label label="required" /></td>
            <td><code>number</code></td>
            <td>Number of decimal places to round to.</td>
        </tr>
    </tbody>
</table>

#### Returns
`Decimal` - Rounded value

#### Example

```ts
const d = new Decimal('19.995');
console.log(d.round(2).toString()); // '20.00'
```

---

### `.equals(other)` {#equals}

Check if two decimals are equal.

```ts title="Syntax"
decimal.equals(other)
```

#### Returns
`boolean` - True if equal

---

### `.compare(other)` {#compare}

Compare two decimals.

```ts title="Syntax"
decimal.compare(other)
```

#### Parameters
<table>
    <thead>
        <tr>
            <th>Parameter</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><code>other</code> <label label="required" /></td>
            <td><code>Decimal</code></td>
            <td>Decimal to compare against.</td>
        </tr>
    </tbody>
</table>

#### Returns
`number` - Returns `-1` if less than, `0` if equal, `1` if greater than

#### Example

```ts
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()` {#iszero}

Check if the decimal is zero.

```ts title="Syntax"
decimal.isZero()
```

#### Returns
`boolean` - True if the value is zero

#### Example

```ts
const zero = new Decimal('0');
console.log(zero.isZero()); // true

const nonZero = new Decimal('1');
console.log(nonZero.isZero()); // false
```

---

### `.isNegative()` {#isnegative}

Check if the decimal is negative.

```ts title="Syntax"
decimal.isNegative()
```

#### Returns
`boolean` - True if the value is negative

#### Example

```ts
const neg = new Decimal('-5');
console.log(neg.isNegative()); // true

const pos = new Decimal('5');
console.log(pos.isNegative()); // false
```

## Complete examples

### Financial calculations

```ts
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.48925
```

### Order total calculation

```ts
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

```ts
// 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

```ts
// 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

```ts
// 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

```ts
// 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

```ts
// 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

```ts
// 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

```ts
// 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 precision
```

### 3. Convert to string for display

```ts
// 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

```ts
// 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

```ts
// 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.3
```

### Premature conversion to number

```ts
// Problem: Loses precision
const result = price.toFloat() + tax.toFloat();

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

## See also

- [Data types overview](/docs/reference/javascript/api/values/) - All custom data types
- [Query builders](/docs/reference/javascript/api/queries/) - Using Decimal in queries
- [SurrealQL decimal](/docs/reference/query-language/language-primitives/data-types/numbers.md) - Database decimal type
