What is a Ledger and Why Floating Points Are Not Recommended?

daniloab

Danilo Assis

Posted on June 21, 2024

What is a Ledger and Why Floating Points Are Not Recommended?

Portugue Version

What is Ledger Series

  1. What is a Ledger and why you need to learn about it?
  2. What is Ledger and why does it need Idempotence?
  3. What is a Ledger and Why Floating Points Are Not Recommended?

In the realm of financial transactions and ledgers, accuracy is paramount. However, using floating point numbers to represent monetary values can lead to significant issues due to their inherent imprecision. This is why it's crucial to understand the problems with floats and consider alternative approaches.

Why Floating Points Are Problematic

Floating point numbers are a common way to represent real numbers in computing. However, they are not suitable for precise financial calculations due to rounding errors. Here are a few examples illustrating the issue:

console.log(0.1 + 0.2); // Expected: 0.3, Actual: 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // Expected: true, Actual: false
Enter fullscreen mode Exit fullscreen mode

These small inaccuracies can accumulate over many transactions, leading to significant errors in financial records.

Using Cents or Decimal128

To avoid these pitfalls, it's recommended to represent monetary values in the smallest units (like cents) or use a data type designed for high precision, such as Decimal128 in MongoDB. This ensures that all calculations are exact, maintaining the integrity of financial data.

Updating the Example to Use Cents

We'll update our previous example to store amounts in cents instead of dollars, ensuring precision in our calculations.

Define the structure of the ledger in MongoDB using cents:

{
  _id: ObjectId("60c72b2f9b1d8e4d2f507d3a"),
  date: ISODate("2023-06-13T12:00:00Z"),
  description: "Deposit",
  amount: 100000, // Amount in cents
  balance: 100000, // Balance in cents
  transactionId: "abc123"
}
Enter fullscreen mode Exit fullscreen mode

Function to add a new entry to the ledger and calculate the balance using cents:

const { MongoClient } = require('mongodb');

async function addTransaction(description, amount, transactionId) {
  const url = 'mongodb://localhost:27017';
  const client = new MongoClient(url);

  try {
    await client.connect();
    const database = client.db('finance');
    const ledger = database.collection('ledger');

    const existingTransaction = await ledger.findOne({ transactionId: transactionId });

    if (existingTransaction) {
      console.log('Transaction already exists:', existingTransaction);
      return;
    }

    const lastEntry = await ledger.find().sort({ date: -1 }).limit(1).toArray();

    const lastBalance = lastEntry.length > 0 ? lastEntry[0].balance : 0;

    const newBalance = lastBalance + amount;

    const newEntry = {
      date: new Date(),
      description: description,
      amount,
      balance: newBalance,
      transactionId: transactionId
    };

    await ledger.insertOne(newEntry);

    console.log('Transaction successfully added:', newEntry);
  } finally {
    await client.close();
  }
}

addTransaction('Deposit', 50000, 'unique-transaction-id-001'); // Amount in cents
Enter fullscreen mode Exit fullscreen mode

Of course, if you are in prod making a change like this one it will need a migration of database. With mongo, this is easier. You can check how we handle this in our blogpost Zero Downtime Database Migrations at Woovi

The goal here is show what you can learn from common mistakes

Woovi APIs Use Cents

Woovi, a modern financial services platform, utilizes cents in their APIs to ensure precision and avoid the pitfalls of floating-point arithmetic. By doing so, they maintain the accuracy and reliability of financial transactions, which is crucial for both their operations and their customers' trust.

Conclusion

Implementing idempotency in your ledger system is crucial for maintaining accurate and reliable financial records. By ensuring that each transaction is only recorded once, you can prevent duplicate entries and maintain the integrity of your data.

As we have seen, idempotency is not just a technical detail but a fundamental principle that helps build robust and fault-tolerant systems. Similarly, using cents instead of floating points ensures precise financial calculations. In our next blog post, we will explore more advanced topics in ledger management and how to handle other challenges such as concurrency and eventual consistency.

Stay tuned for more insights into building reliable financial systems!


Visit us Woovi!


Follow me on Twitter

If you like and want to support my work, become my Patreon

Want to boost your career? Start now with my mentorship through the link

https://mentor.daniloassis.dev

See more at https://linktr.ee/daniloab

Photo of Andrew Spencer in Unsplash

πŸ’– πŸ’ͺ πŸ™… 🚩
daniloab
Danilo Assis

Posted on June 21, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related