[Ed: reworded - sorry for the confusing initial wording. Also thanks to all those who suggested using integers, but for several reasons I must use float64
.]
I have a floating point value that I want to round to 1 decimal if more than 100 and no decimals if more than 1000, otherwise round to 2 decimals. This works:
func r(f float64) float64 {
if f >= 999.5 {
return math.Round(f)
}
if f >= 99.95 {
return math.Round(f*10) / 10
}
return math.Round(f*100) / 100
}
but I'm wondering if this would be better:
func r(f float64) float64 {
if f >= 999.5 {
return math.Round(f)
}
if f*10 >= 999.5 { // **** only changed line ****
return math.Round(f*10) / 10
}
return math.Round(f*100) / 100
}
This is safer as 99.95 is not represented exactly using floating point with a binary exponent. (I believe the Go language requires use of IEEE fp format which has a binary exponent.) 999.5 is exactly representable as a fp value.
However, my tests (using math.NextAfter()
) show that the first solution works perfectly well for all values from 99.94999999 to 99.95000001. 1st question: I am worrying unduly.
The problem with the 2nd solution is that I am worried that f*10
may be evaluated twice. 2nd question: is there any guarantee the optimiser will ensure that it is only done once.