-
Notifications
You must be signed in to change notification settings - Fork 18k
strconv: incorrect rounding to nearest even #21714
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
Comments
Change https://golang.org/cl/60730 mentions this issue: |
I don't see what's “incorrect” about it. The spec gives exactly what happens: the arbitrary-precision constant 3.5 is rounded to its default type, which is then rounded to one digit. The only reason to expect any different would be if floating-point constants converted to an arbitrary-precision floating-point type by default instead of a fixed-precision type. |
@bcmills This has little to do with arbitrary precision constants since we get the same results if we do everything in float64 arithmetic, starting from numbers that can be represented exactly. But I'm wrong nevertheless: After an exact constant In the case of At this point all we have is that float64 value The following program computes the exact errors as well as exact and strconv rounded values and it turns out that for my original example above, the strconv rounded results are less than 0.05 away from the actual float64 values which means that they are correctly rounded. @mpvl I'm closing this as working as expected. You may need to revisit https://golang.org/cl/60730. |
Will undo that CL and focus on allowing people to use their own numeric types. |
Removed AppendFloat-based rounding to not hit bug golang/go#21714. Fixed several edge cases and implemented some missing features that were exposed as a result of having to fall back on our own rounding. This also fixed some previously unnoticed bugs. Change-Id: Id675bdc9a9099eda0b9c31e5166b510b714887b5 Reviewed-on: https://go-review.googlesource.com/60730 Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Nigel Tao <nigeltao@golang.org>
Change https://golang.org/cl/61492 mentions this issue: |
Hopefully final attempt to work around golang/go#21714. Prevent double rounding: If we apply rounding down the road we get a large number of decimals. Otherwise we ask for the smallest representation. Change test cases to not use numbers that will round incorrectly. Change-Id: If5c8fbcb27a867de28caf847e9ba828718482841 Reviewed-on: https://go-review.googlesource.com/61492 Run-TryBot: Marcel van Lohuizen <mpvl@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
The following statements
produce
(https://play.golang.org/p/kLC7Ap0cpP).
However, assuming rounding to nearest even, one would expect the result to be
(The examples use fmt.Printf but the culprit is in the underlying strconv code. The documentation doesn't explicitly state that it rounds to nearest even, but that is definitively the intent of the implementation which contains code and comments to that effect.).
The problem of course is that these numbers cannot be accurately represented in binary form and when it comes to the rounding decision, what should be
.5
is sometimes below or above that value.That said, the correct result could in fact be obtained if rounding were done on the shortest decimal representation that produces the incoming number, that is if rounding where done on the output of using the "%g" format (or
strconv.FormatFloat
with precision -1). Unfortunately, computing that representation is much more expensive than what happens now.We can probably not fix this. For one, it's been like this forever. Also, a corresponding C program
produces the same (incorrect) result. And so does
math/big.Float
formatting with the same arguments (since the code mirrors the strconv code).But we should probably document it and perhaps even provide a "correct" routine for cases where this truly matters.
The text was updated successfully, but these errors were encountered: