Navigation Menu

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 handles prec differently from the doc with fmt='g' #25082

Closed
musiphil opened this issue Apr 25, 2018 · 5 comments
Closed
Labels
Documentation FrozenDueToAge help wanted NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@musiphil
Copy link

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

go version go1.10.1 linux/amd64

Does this issue reproduce with the latest release?

Yes

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

GOARCH="amd64"
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"

What did you do?

fmt.Println(strconv.FormatFloat(1.5, 'g', 6, 64))
https://play.golang.org/p/WRHc89mjuSG

What did you expect to see?

1.50000

https://golang.org/pkg/strconv/#FormatFloat says:

The precision prec controls the number of digits […]. For 'g' and 'G' it is the total number of digits.

I gave prec=6, so the total number of digits should be 6.

What did you see instead?

1.5

The total number of digits is 2.

@FiloSottile FiloSottile added this to the Go1.11 milestone Apr 25, 2018
@FiloSottile FiloSottile added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Apr 25, 2018
@pam4
Copy link

pam4 commented Apr 25, 2018

Workaround: use fmt.Sprintf("%#.*g", 6, 1.5) in place of strconv.FormatFloat(1.5, 'g', 6, 64).

I agree that the doc and the implementation are in contradiction, and either one or the other should be fixed.

I'm not sure what is the basis for removing trailing zeros.
The number of significant digits in a number is not part of its float representation, that's why we ask the caller about it.
On the contrary the number of significant digits in a number, is part of its string representation, and by removing trailing zeros we are altering it.

The relevant piece of code seems to be here: https://golang.org/src/strconv/ftoa.go?s=5694:5737#L206

If the current implementation is preserved, I propose to fix like this:

The precision prec controls the number of digits (excluding the exponent) printed by the 'e', 'E', 'f', 'g', and 'G' formats. For 'e', 'E', and 'f' it is the number of digits after the decimal point. For 'g' and 'G' it is the total number of digits maximum number of significant digits (trailing zeros are removed). The special precision -1 uses the smallest number of digits necessary such that ParseFloat will return f exactly.

Verbs %g and %G in the fmt package follow C behavior, which is fine, but again the doc is not clear enough:

For floating-point values, width sets the minimum width of the field and precision sets the number of places after the decimal, if appropriate, except that for %g/%G precision sets the total number of significant digits maximum number of significant digits (trailing zeros are removed). For example, given 12.345 the format %6.3f prints 12.345 while %.3g prints 12.3. The default precision for %e, %f and %#g is 6; for %g it is the smallest number of digits necessary to identify the value uniquely.

Yes, the doc for the # flag has the missing information, but you won't find it if you just look for "precision".

@musiphil
Copy link
Author

Thanks, and I agree in general.

I've always been mindful of communicating the correct number of significant digits. With fmt and %g we at least have the # flag, but it is very unfortunate that strconv.FormatFloat doesn't offer any option.

Ideally, strconv.FormatFloat should offer such an option (and maybe support for other flags as well) and the post-processing in fmt could be simplified, offering on-par features to the users of fmt and strconv.FormatFloat. (It may not be easy without modifying the interface of strconv.FormatFloat, though.) Without that, I would personally favor fixing the implementation, but that would mean a small change in the behavior of current programs using it, so we may have to fix the documentation instead.

@ianlancetaylor
Copy link
Contributor

I don't think we should change the code, so marking this as a documentation fix.

@ianlancetaylor ianlancetaylor added the NeedsFix The path to resolution is known, but the work has not been done. label Jun 29, 2018
@gopherbot gopherbot removed the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Jun 29, 2018
@ianlancetaylor ianlancetaylor modified the milestones: Go1.11, Unplanned Jun 29, 2018
@danicat
Copy link
Contributor

danicat commented Jul 31, 2018

Hi! It seems that no one is working on this right now... have we agreed that this is just a doc change? May I do it?

@gopherbot
Copy link

Change https://golang.org/cl/127135 mentions this issue: strconv: clarify "g" and "G" precision in the docs

@golang golang locked and limited conversation to collaborators Aug 1, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Documentation FrozenDueToAge help wanted NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

6 participants