I think the OP is getting caught up by confusing "decimal precision" with some property of a binary floating point number.
To OP: You need to think of x here as a binary floating point number, and not a real number. It does not have infinite precision, and its properties are governed by the restrictions of binary floating point, not decimal floating point. Importantly, there is no exact representation of 10^-5 in binary. If you are concerned with how things print in decimal, you should do this by converting them to decimal, and the generally used advice is to do so as late as possible - namely, at the point when you are printing them for a human. (And for that, Steele's article is the absolute bog standard way to do it, don't try it yourself because there are many subtleties!) There is no such thing, really, as a binary floating point number with N digits of decimal precision, in the sense that it has some stable property you might have expected from the properties of real numbers. Thomas -----Original Message----- From: 'Peter Weinberger (温博格)' via golang-nuts <golang-nuts@googlegroups.com> Sent: Wednesday, August 13, 2025 2:09 PM To: Alexander Ertli <ertli.alexan...@googlemail.com> Cc: robert engels <reng...@ix.netcom.com>; Jochen Voss <jochen.v...@gmail.com>; golang-nuts <golang-nuts@googlegroups.com> Subject: Re: [go-nuts] Rounding to k digits This message was sent by an external party. The canonical reference on this is by Guy Steele, "How to Print Floating Point Numbers Accurately" On Wed, Aug 13, 2025 at 9:07 AM 'Alexander Ertli' via golang-nuts <golang-nuts@googlegroups.com> wrote: > > Hi Jochen, > > I think it's possible with a trick. > > My first naive thought on how to solve this is to simply shift the decimal > point over, do the rounding on the whole number, and then shift it back. > > import "math" > // Round performs rounding by shifting the decimal, rounding, and shifting > back. > func Round(x float64, digits int) float64 { > scale := math.Pow(10, float64(digits)) > return math.Round(x*scale) / scale > } > > https://go.dev/play/p/_DVsD45FAKb > > > Am Mi., 13. Aug. 2025 um 14:51 Uhr schrieb robert engels > <reng...@ix.netcom.com>: >> >> Read up on numerical analysis - what you are asking for is impossible >> :) >> >> You need to convert to a string, or use BCD/fixed place values - like >> github.com/robaho/fixed >> >> On Aug 13, 2025, at 7:42 AM, Jochen Voss <jochen.v...@gmail.com> wrote: >> >> Dear all, >> >> I would like to define a function "func Round(x float64, digits int) >> float64" which rounds to the given number of digits, in the sense that I >> want "strconv.FormatFloat(x, 'f', -1, 64)" to show at most the given number >> of digits after the decimal point. >> >> The following naive approach does not work: >> >> func Round(x float64, digits int) float64 { eps := >> math.Pow10(-digits) return math.Round(x/eps) * eps } >> >> For example for rounding math.Pi to five digits I get "3.1415900000000003" >> instead of "3.14159". https://go.dev/play/p/gRtHG6ZgTjj . >> >> Anthropic's Claude suggested the following: >> >> func Round(x float64, digits int) float64 { if digits <= 0 { pow := >> math.Pow10(-digits) return math.Round(x/pow) * pow } >> >> format := "%." + strconv.Itoa(digits) + "f" >> s := fmt.Sprintf(format, x) >> result, _ := strconv.ParseFloat(s, 64) >> >> return result >> } >> >> This seems to work, but also seems quite inefficient. >> >> Is there a better way? >> >> All the best, >> Jochen >> >> PS.: Here is some testing code for experimenting >> https://go.dev/play/p/Xcd6fTvYend >> >> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts+unsubscr...@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/7d3ccdd4-d88b-4eba-8a36-02b51b7751e1n%40googlegroups.com. >> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts+unsubscr...@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/234384D7-17A3-45B3-959C-8CE0D3F44BF5%40ix.netcom.com. > > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > To view this discussion visit > https://groups.google.com/d/msgid/golang-nuts/CAC4E5Zk1bq7z%2B%2BePzBRnsCoEYWsAW0RJzAd6KvjqNeJyRayDOQ%40mail.gmail.com. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/CAOUkXSq6KRgyyRWd1MJiaERxc%2BQYO%2BoGC3SSwhQ5_CGZ2WY05A%40mail.gmail.com. -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/f86ae360d1ee4561b0b7537f3d98463d%40deshaw.com.