I was very surprised when started to work with the type of floating-point (float32 & float64). In this example, I have collected only a few options from the set:
package main
import (
    "fmt"
)
func main() {
    var sum, price, count float64
    sum, price, count = 1000, 166.67, 5
    fmt.Printf("%v - %v * %v = %v\n", sum, price, count, sum-price*count)
    price, count = 7.35, 3
    fmt.Printf("%v * %v = %v\n", price, count, price*count)
    var a, b, c float64
    a, b = 2, 1.1
    fmt.Printf("%v - %v = %v\n", a, b, a-b)
    a, b, c = 0.1, 0.2, 0.3
    fmt.Printf("%v + %v - %v = %v\n", a, b, c, a+b-c)
}
It prints:
1000 - 166.67 * 5 = 166.6500000000001
7.35 * 3 = 22.049999999999997
2 - 1.1 = 0.8999999999999999
0.1 + 0.2 - 0.3 = 5.551115123125783e-17
2.4 / 0.1 = 23.999999999999996
The problem occurs after the execution of arithmetic operations: +, -, *, /
Now I'm absolutely not sure that my algorithm would give me the correct result.
I solved the problem by normalized the value after each operation - rounded up to the lower accuracy than the error:
package main
import (
    "fmt"
    "math"
)
func main() {
    var sum, price, count float64
    sum, price, count = 1000, 166.67, 5
    fmt.Printf("%v - %v * %v = %v\n", sum, price, count, Normalize(sum-price*count))
    price, count = 7.35, 3
    fmt.Printf("%v * %v = %v\n", price, count, Normalize(price*count))
    var a, b, c float64
    a, b = 2, 1.1
    fmt.Printf("%v - %v = %v\n", a, b, Normalize(a-b))
    a, b, c = 0.1, 0.2, 0.3
    fmt.Printf("%v + %v - %v = %v\n", a, b, c, Normalize(a+b-c))
    a, b = 2.4, 0.1
    fmt.Printf("%v / %v = %v\n", a, b, Normalize(a/b))
}
func Normalize(value float64) float64 {
    return RoundViaFloat(value, 4)
}
func RoundViaFloat(x float64, prec int) float64 {
    var rounder float64
    pow := math.Pow(10, float64(prec))
    intermed := x * pow
    _, frac := math.Modf(intermed)
    x = .5
    if frac < 0.0 {
        x = -.5
    }
    if frac >= x {
        rounder = math.Ceil(intermed)
    } else {
        rounder = math.Floor(intermed)
    }
    return rounder / pow
}
It prints:
1000 - 166.67 * 5 = 166.65
7.35 * 3 = 22.05
2 - 1.1 = 0.9
0.1 + 0.2 - 0.3 = 0
2.4 / 0.1 = 24
But it seems to me, is not normal :-(
Can anyone help me solve this problem?
thanx
