I have a scenario where I receive a float64 value, but must send it down the wire to another service as a float32 value. We know the received value should always fit into a float32. However, to be safe I want to log the case where we are losing data by converting to float32.
This code block does not compile, since you can't compare float32 to float64 directly.
func convert(input float64) (output float32, err error) {
const tolerance = 0.001
output = float32(input)
if output > input tolerance || output < input-tolerance {
return 0, errors.New("lost too much precision")
}
return output, nil
}
Is there an easy way to check that I am hitting this condition? This check will happen at high frequency, so I want to avoid doing string conversions.
CodePudding user response:
You can convert back the float32
value to float64
, just for the validation:
func convert(input float64) (output float32, err error) {
const tolerance = 0.00000001
output = float32(input)
if math.Abs(float64(output)-input) > tolerance {
return 0, errors.New("lost too much precision")
}
return output, nil
}
(Note: edge cases like NaN
are not checked.)
Testing it:
fmt.Println(convert(0.1))
fmt.Println(convert(0.123456789))
fmt.Println(convert(math.Pi))
fmt.Println(convert(math.MaxFloat32))
fmt.Println(convert(math.MaxFloat64))
Output (try it on the Go Playground):
0.1 <nil>
0.12345679 <nil>
0 lost too much precision
3.4028235e 38 <nil>
0 lost too much precision
CodePudding user response:
Yes. Check that the value does not exceed the upper or lower value limit. Then ensure the 52 - 23 least significant bits are 0. (in a nutshell)