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: FormatFloat returns value out of IEEE float64 range #18409

Closed
tejasmanohar opened this issue Dec 21, 2016 · 5 comments
Closed

strconv: FormatFloat returns value out of IEEE float64 range #18409

tejasmanohar opened this issue Dec 21, 2016 · 5 comments

Comments

@tejasmanohar
Copy link

tejasmanohar commented Dec 21, 2016

Please answer these questions before submitting your issue. Thanks!

https://play.golang.org/p/BsjbwEDp84

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

go version go1.7.4 darwin/amd64

(but this doesn't seem to be a new thing)

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

GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"

but can replicate in play.golang.org

What did you do?

https://play.golang.org/p/BsjbwEDp84

What did you expect to see?

I expected 2.33125e-315 to lose precision when stored as float64 by Go or at least when converted to string because it's more precise / closer to 0 than 1e-308.

What did you see instead?

Go handled this number fine even though it was out of range.

The 11 bit width of the exponent allows the representation of numbers between 10^−308 and 10^308, with full 15–17 decimal digits precision. By compromising precision, the subnormal representation allows even smaller values up to about 5 × 10^-324
From Wikipedia

I believe Go is using the "subnormal representation" mentioned here. If that's the case, is there a reliable way to convert to float64 string as precise as the standard representation can handle? I think using -1 as the precision measure is throwing Go off since it can handle more precise numbers than the IEEE standard (but I may totally be wrong-- I'm not that familiar/strong here).

PS: If you're wondering how I came to this, I'm working on some ETL software, and the provided number 2.33125e-315 does not work for Redshift's float8/double (8 bytes, 64 bits) type.

@odeke-em
Copy link
Member

/cc @griesemer

@griesemer
Copy link
Contributor

It's a denormalized number. It does lose precision eventually: https://play.golang.org/p/xqfMMXrXWc

Working as expected.

@griesemer
Copy link
Contributor

@tejasmanohar Please use the usual channels (not the issue tracker) for general Go questions in the future. Thanks.

Regarding the -1 precision, the documentation is clear: "The special precision -1 uses the smallest number of digits necessary such that ParseFloat will return f exactly." ( https://golang.org/pkg/strconv/#FormatFloat ).

And as you already cited Wikipedia, it says right there that the range allows even smaller values up to approx. 5 × 10^-324. The number you're using can still be represented because it's mantissa (2.33125) is apparently short enough to still fit.

In short, the value is not out of float64 range.

@tejasmanohar
Copy link
Author

This makes sense. Sorry about that! I think Redshift's string parsing has a bug where it doesn't happen denormalized numbers (unless that's how it's suppoesd to work... we'll see). This is not a Go problem, sorry :)

@tejasmanohar
Copy link
Author

Came to this btw https://play.golang.org/p/NOOG49ag-E

@golang golang locked and limited conversation to collaborators Dec 21, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants