DEV Community

Cover image for Handling Currency In Golang And Other Programming Language
dikac for Tentang Anak Tech Team

Posted on

Handling Currency In Golang And Other Programming Language

Handling currency in programming languages is a critical aspect of software development, especially for applications dealing with financial transactions, e-commerce, banking, and accounting systems. Accurate representation and manipulation of currency values are essential to avoid errors that can lead to significant financial discrepancies.

This article will explore best practices in handling currency with example in Go languages.

Precision and Accuracy

One of the primary concerns when dealing with currency is precision. Unlike floating-point numbers, which can introduce rounding errors, currency values require precise representation.

consider following code

package main

import "fmt"

func main() {

    var a float64 = 1.1
    var b float64 = 1.2
    var c float64 = 1.3
    fmt.Println(a + b + c)

}

Enter fullscreen mode Exit fullscreen mode

Above code would print

3.5999999999999996
Enter fullscreen mode Exit fullscreen mode

Since memory of computers is limited, most programming language including Go store floating point based on the IEEE-754 standard using 32 or 64 bits, even using 64-bit precision it’s impossible to store an infinite number of digits, which means these numbers are rounded at some point, making them inherently imprecise, and the more calculation is performed the more they become imprecise.

There is many way to handle this problem like using 3rd party library or the programming language you use has a native support. In Go, there are several libraries, including :

credit to kennfatt for curating this library list

Choosing Library

Choosing the right library for handling currency programming involves several considerations. Here's a guide to help you choose an appropriate decimal library for your needs

1. Accuracy and Precision

Ensure the library supports precision and accuracy suit your requirement. Look for arbitrary precision capabilities if dealing with very large numbers or very precise calculations.

2. Ease of Use

The library should have clear and comprehensive documentation. It should be easy to integrate with your existing codebase and workflows.

3. Performance

Consider the performance impact, especially if you are performing a large number of calculations or operating in a high-frequency trading environment.

4. Feature

Ensure the features suit with your needs, from basic arithmetic like rounding, addition, subtraction multiplication, division to more complex math operation.

5. Community and Support

A well-supported library with an active community can be crucial for getting help and finding solutions to problems. Look for libraries that are actively maintained and updated.

Using 3rd Party

This article will use 3rd party library govalues/decimal for code example, since doc simple and easy to read and suite the need for code demonstration

package main

import (
    "fmt"
    "github.com/govalues/decimal"
)

func main() {

    a, _ := decimal.Parse("1.1")
    b, _ := decimal.Parse("1.2")
    c, _ := decimal.Parse("1.3")

    a, _ = a.Add(b)
    a, _ = a.Add(c)
    fmt.Println(a.String())

}
Enter fullscreen mode Exit fullscreen mode

Above code would print

3.6
Enter fullscreen mode Exit fullscreen mode

In above example has no precision loss, still since memory has a cost and not infinite, digit after the decimal point are still limited, controlling decimal digit is important, in this example you can set the size using decimal.ParseExact()

Storing And Retrieving

Storing in databases also requires careful consideration to maintain precision and consistency.

Use Appropriate Column Types

Most relational databases have specific types for currency values, such as DECIMAL or NUMERIC.

Avoid Floating-Point Storage

Just like in programming, avoid storing currency values as floating-point numbers in databases.

For example in MySQL

CREATE TABLE `users` (
    `id` int,
    `balance` decimal(6, 2)
);
Enter fullscreen mode Exit fullscreen mode

Full MySQL Demonstration in go

package main

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

func main() {

    db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:3306)/test")
    if err != nil {
        panic(err)
    }

    _, err = db.Exec(`
        CREATE TABLE test (
            id int,
            balance_decimal decimal(16, 8),
            balance_float float(16, 8),
            PRIMARY KEY (id)
        );
    `)

    _, err = db.Exec("INSERT INTO test (id, balance_decimal, balance_float) VALUES (1, 1.1, 1.1)")
    _, err = db.Exec(`
        UPDATE test 
            SET 
                balance_decimal = balance_decimal + 1.2 , 
                balance_float   = balance_float + 1.2 
            WHERE id = 1;
    `)
}

Enter fullscreen mode Exit fullscreen mode

Above code would produce

id balance_decimal balance_float
1 2.30000000 2.29999995

Data Transfer

Data transfer also requires careful consideration of precision. a correct format is required

For example in JSON format, using type string guaranteed precision across any programing language

package main

import (
    "encoding/json"
    "log"
)

type Data struct {
    Decimal string  `json:"decimal"`
    Float   float64 `json:"float"`
}

func main() {

    payload := []byte(`{"decimal":"999.99999999999999","float":999.99999999999999}`)

    result := Data{}

    _ = json.Unmarshal(payload, &result)

    log.Print("Decimal: ", result.Decimal)
    log.Print("Float: ", result.Float)

}
Enter fullscreen mode Exit fullscreen mode

Above code would print

Decimal: 999.99999999999999
Float: 1000
Enter fullscreen mode Exit fullscreen mode

Conclusion

Handling currency in programming languages requires careful attention to detail to ensure precision, accuracy, and consistency. By using appropriate data types, libraries, and best practices, developers can avoid common pitfalls and ensure their applications handle currency correctly. Proper handling of currency not only prevents financial errors but also enhances user trust and confidence in the application.

There's no single best library for everyone. Each project has different needs. You should think about what's good and bad about each library based on what your project requires.

External Link

Top comments (0)