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