- read

Inaccurate float32 and float64: how to avoid the trap in Go (golang)

Wacław The Developer 103

Photo by Luis Villasmil on Unsplash

Hi everyone! Let’s talk about floats today. So, let’s take a look on that simple code:

var n float64 = 0
for i := 0; i < 10; i++ {
n += 0.1
println(n == 1)

You will be surprised, but the output will be


So, what about float32?

var n float32 = 0
for i := 0; i < 10; i++ {
n += 0.1
println(n == 1)

Maybe you will be confused now, but the output will be


What is going on?

If try to be short — it is the side effect of how CPU represents the floats.

What will be if i will skip this problem?

  1. You will fail the comparison of values. For example, if you are trying to write progress checks — you will be stuck in a loop (sure this is not the best example):
var progressPercentage float64 = 0
for ; ; {
//Do some work and add to overall progress 1%
progressPercentage += 0.01

//Check if 100% reached (1 will never be reached. Just < or > than 1)
if progressPercentage == 1 {

2. Type conversion between systems (for example between DB and your server) may lead to difference in values. You can imagine what will be with financial reports if statistical data will collect the error many times.

What the solution?

There are many topics for different languages. For example, this topic on Microsoft webpage describes what to do for C developers: https://docs.microsoft.com/en-us/cpp/build/why-floating-point-numbers-may-lose-precision?view=msvc-170

As the easy solution for critical parts of app i found useful this Go lib:

So let’s refactor our code:

package main

import "fmt"
import "github.com/shopspring/decimal"

main() {
m := decimal.NewFromFloat(0)
for i := 0; i < 100; i++ {
m = m.Add(decimal.NewFromFloat(0.01))

Now, the output will be


Thanks for reading. I hope it was interesting.