Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Incorrect encoding of float32 numbers #1002

Closed
hemantjadon opened this issue Sep 8, 2021 · 3 comments
Closed

Bug: Incorrect encoding of float32 numbers #1002

hemantjadon opened this issue Sep 8, 2021 · 3 comments

Comments

@hemantjadon
Copy link
Contributor

zap.Float32 field types incorrectly formats the float32 numbers. The precision (bitSize) information is lost while converting float32.
Eg. 2.71 is formatted as 2.7100000381469727

package main

import (
	"go.uber.org/zap"
)

func main() {
    l, _ := zap.NewProduction()

    l.Info("test", zap.Float32("key", 2.71))
}

Got output

{"level":"info","ts":1257894000,"caller":"sandbox3599029287/prog.go:10","msg":"test","key":2.7100000381469727}

Expected output

{"level":"info","ts":1257894000,"caller":"sandbox3599029287/prog.go:10","msg":"test","key":2.71}

Reference

https://play.golang.org/p/3IkJONIZ_xN

@hemantjadon
Copy link
Contributor Author

This is due to the fact, that correct bitSize information is not reaching the enc.appendFloat method, as on zapcore/json_encoder.go#L300, float32 value is being converted to a float64, and then is passed to enc.AppendFloat64, instead of being passed to enc.AppendFloat32

package main

import (
	"fmt"
	"strconv"
)

func main() {
	var f64 float64 = 2.71
	var f32 float32 = 2.71
	fmt.Println(strconv.FormatFloat(f64, 'f', -1, 64))          // 2.71
	fmt.Println(strconv.FormatFloat(float64(f32), 'f', -1, 32)) // 2.71
	fmt.Println(strconv.FormatFloat(float64(f32), 'f', -1, 64)) // 2.7100000381469727
}

Reference

https://play.golang.org/p/5_f8UMKIFMT

@abhinav
Copy link
Collaborator

abhinav commented Sep 8, 2021

Thanks for reporting! We'll try to have this fixed shortly.

(internal ref: GO-860)

manjari25 added a commit that referenced this issue Sep 8, 2021
Refs: 
* #1002
* Internal ticket: GO-860
manjari25 added a commit that referenced this issue Sep 8, 2021
This commit fixes incorrect float32 encoding. A test
case is also added.

Refs: 
* #1002
* Internal ticket: GO-860
@manjari25
Copy link
Contributor

Released on v1.19.1

abhinav added a commit that referenced this issue Sep 10, 2021
Per #1010, #1002, and #995, some of the corner cases where precision is
changed or lost aren't fully tested.

Add test cases for corner cases for a number of these:

- complex{64, 128}:  Test incorrect precision and negatives
- float{32, 64}: Test incorrect precision
- int{8, 16, 32, 64}: Test minimum and maximum values
- uint{8, 16, 32, 64}: Test maximum values

Per #1010, the test for complex64 incorrect precision is currently
failing.
abhinav added a commit that referenced this issue Sep 10, 2021
Converting to Complex128 meant that the real and imaginary components of
the Complex64 were encoded as float64s which, like #1002, ended up
those components with the incorrect precision.

Fix this by adding a precision parameter to appendComplex tp specify the
precision with which the two components of the complex number should be
encoded.
abhinav added a commit that referenced this issue Sep 10, 2021
Converting `complex64` to `complex128` meant that
the real and imaginary components of the `complex64` value
were encoded as `float64` values which,
similar to #1002, encoded them with incorrect precision.

Fix this by adding a precision parameter during encoding to specify
the precision with which the components should be encoded.

Guard against other such cases where there's loss of precision
by adding tests for several such corner cases for
complex, float, int, and uint.

This has no significant performance impact on my laptop.
(The drop is likely a false positive.)

```
name                          old time/op  new time/op  delta
ZapJSONFloat32AndComplex64-4   491ns ±22%   442ns ± 6%  -10.00%  (p=0.000 n=9+9)
```

Fixes #1010
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants