Hi Alexander, Thanks, this is interesting. My original
func Round(x float64, digits int) float64 { eps := math.Pow10(-digits) return math.Round(x/eps) * eps } leads to near-immediate fuzzing failures, whereas your func Round(x float64, digits int) float64 { scale := math.Pow(10, float64(digits)) return math.Round(x*scale) / scale } has now survived 4 minutes of fuzzing. Maybe the difference is that scale can be represented exactly, while eps has truncation error? Many thanks, Jochen On Wednesday, 13 August 2025 at 14:07:46 UTC+1 Alexander Ertli 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 < > ren...@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 <joche...@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...@googlegroups.com. >> To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/7d3ccdd4-d88b-4eba-8a36-02b51b7751e1n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/7d3ccdd4-d88b-4eba-8a36-02b51b7751e1n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> >> -- >> 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...@googlegroups.com. >> > To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/234384D7-17A3-45B3-959C-8CE0D3F44BF5%40ix.netcom.com >> >> <https://groups.google.com/d/msgid/golang-nuts/234384D7-17A3-45B3-959C-8CE0D3F44BF5%40ix.netcom.com?utm_medium=email&utm_source=footer> >> . >> > -- 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/27ae793c-3018-46c4-b2d3-4f2854ffdbb2n%40googlegroups.com.