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

math: MaxFloat32/64 and SmallestNonzeroFloat32/64 value comments misleading #61230

Closed
extemporalgenome opened this issue Jul 7, 2023 · 3 comments

Comments

@extemporalgenome
Copy link
Contributor

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

Playground 1.20 as of Fri Jul 7 15:17:35 UTC 2023.

Does this issue reproduce with the latest release?

Yes.

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

Playground

What did you do?

https://go.dev/play/p/HZ_Nr7FpU9d

strconv.FormatFloat(math.MaxFloat64, 'e', -1, 64)

What did you expect to see?

1.79769313486231570814527423731704356798070e+308

(since this longer value is listed in the doc comment for math.MaxFloat64)

What did you see instead?

1.7976931348623157e+308

This applies to MaxFloat32, MaxFloat64, SmallestNonzeroFloat32, and SmallestNonzeroFloat64.

Since all of these cases are rational numbers defined in terms of the type itself, I expect their doc comments to have exactly the same value that strconv.FormatFloat would produce with -1 precision.

Note that C# (link) and Java (link) also express the constant in terms of the value that strconv.FormatFloat prints with -1 precision.

@extemporalgenome
Copy link
Contributor Author

Further request for clarification: float64(math.MaxFloat32) != float64(float32(math.MaxFloat32))

https://go.dev/play/p/feXsT2QSRIU

Why doesn't math.MaxFloat32 exactly represent the maximum finite value that can be stored in a float32? It may happen to produce the maximum-finite bit-pattern when stored in a float32, but is it still reasonable to claim that this is the maximum finite value that a float32 holds when it's not exactly that same finite value?

@randall77
Copy link
Contributor

From strconv.FormatFloat:

The special precision -1 uses the smallest number of digits necessary such that ParseFloat will return f exactly.

So the "actual" you're generating here is not the actual value contained in the float. It is the shortest possible string that parses to that float.

fmt.Println I think also does not print with arbitrary precision. (It prints with "default format", whatever that means.)

If you print with %.0f it will give you the exact value. The resulting value is what is listed in comments for float32, and probably would be listed for float64 only it is too long.

	f32 := float32(math.MaxFloat32)
	fmt.Printf("f32:   %.0f\n", f32)
	fmt.Printf("f32    %x\n", math.Float32bits(f32))
	f64 := float64(math.MaxFloat64)
	fmt.Printf("f64:   %.0f\n", f64)
	fmt.Printf("f64    %x\n", math.Float64bits(f64))

@extemporalgenome
Copy link
Contributor Author

Ah. I misunderstood. Thanks for the explanation!

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

No branches or pull requests

2 participants