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

strconv: inaccurate string to float64 conversion ParseFloat #36657

Open
g7r opened this issue Jan 20, 2020 · 4 comments
Open

strconv: inaccurate string to float64 conversion ParseFloat #36657

g7r opened this issue Jan 20, 2020 · 4 comments

Comments

@g7r
Copy link
Contributor

@g7r g7r commented Jan 20, 2020

What version of Go are you using (go version)?

$ go version
version go1.13 linux/amd64

Does this issue reproduce with the latest release?

Not sure. But https://play.golang.org/p/izkaZ-XBog5 reproduces the bug.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

Here's the code: https://play.golang.org/p/izkaZ-XBog5

I'm converting string "1090544144181609348835077142190" to float64 with strconv.ParseFloat("1090544144181609348835077142190", 64) and it returns incorrect value.

What did you expect to see?

It is expected that 1090544144181609419040633126912 should be returned as the closest value representable by float64. The difference between string value and correct float64 value is -70205555984722 (see https://www.wolframalpha.com/input/?i=1090544144181609348835077142190-1090544144181609419040633126912)

What did you see instead?

strconv.ParseFloat(...) actually returns 1090544144181609278303144771584. The difference between string value and returned float64 value is 70531932370606 (see https://www.wolframalpha.com/input/?i=1090544144181609348835077142190-1090544144181609278303144771584)

Additional info

Go compiler correctly converts float64 literals to float64 constants, as you can see in Playground example https://play.golang.org/p/izkaZ-XBog5

@randall77

This comment has been minimized.

Copy link
Contributor

@randall77 randall77 commented Jan 20, 2020

I can confirm. It seems like the fast path in strconv/atof.go:627, particularly the AssignDecimal call, is to blame. If I turn the optimize flag off, the bug goes away.
This has been an issue since at least 1.11.
@griesemer

@randall77 randall77 added this to the Go1.15 milestone Jan 20, 2020
@odeke-em odeke-em changed the title Inaccurate string to float64 conversion in strconv.ParseFloat strconv: inaccurate string to float64 conversion ParseFloat Jan 22, 2020
@smasher164

This comment has been minimized.

Copy link
Member

@smasher164 smasher164 commented Jan 22, 2020

This behavior has existed since go 1, so it wasn't introduced in any recent release. Digging into extfloat now.

@ALTree

This comment has been minimized.

Copy link
Member

@ALTree ALTree commented Jan 23, 2020

The ParseFloat doc says:

If s is well-formed and near a valid floating-point number, ParseFloat returns the nearest floating-point number rounded using IEEE754 unbiased rounding.

So it appears that it doesn't unconditionally guarantee to always return the closest IEEE754 number... only if the argument is "near a valid floating-point number" (whatever that means). I believe that your number does not qualify as "near a valid floating-point number".

@smasher164

This comment has been minimized.

Copy link
Member

@smasher164 smasher164 commented Jan 24, 2020

Also, the CL associated with #15672 solves this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants
You can’t perform that action at this time.