Arithmetic avarage with floating point


(Che) #1

Hello, silly question but the following snippet contains an error that I can’t find

var (
        an float64
    	n, avg = 0, 0.
   )

for ; ; n++ {
	fmt.Print("number? ")
	fmt.Scan(&an)
	if an == 0. {
		break
	}
	avg += an
}

if n != 0 {
	fmt.Println(avg / float64(n))
}

The program output is

number? 5.1
number? 2.1
number? 0
3.5999999999999996

rather than 3.6, why?


(Lutz Horn) #2

See https://floating-point-gui.de/


(Norbert Melzer) #3

Because of the known imprecision that floats are accomponied with.

If you need precise values, you need a precise type.

There are a lot of blog posts available around this topic, I picked the first three hits on google about “floating point money” (as money is the most common example used as “precise value”):

(* I have not read any one of those recently, they are just the first google hits)


(Che) #4

OK, have you any tips how I should round up the result? Maybe by using the systematic error constant
.0000000000000005?


(Norbert Melzer) #5

You can’t round anything up or down to a value that is not representable.

All links we gave you, tell about the inherint imprecission of floating point computations, and either you are in a field where you can safely allow this imprecissions (eg. computer graphics) or not (eg. money).


(Che) #6

OK I found with Google the following snippet
https://play.golang.org/p/KNhgeuU5sT
that resolves the problem
Thank you.


(Norbert Melzer) #7

That will just cause further problems. If you need precision, then use a type that has precision.

If its just for display purpose, then use proper annotations in the call to fmt.Printf.


(Che) #8

OK. I can use fmt.Printf in this case to round up the result or math.big to process input data that has precision as 3.5999999999999996. Right?