Go: math: add a Round function

Created on 28 Dec 2012  Â·  25Comments  Â·  Source: golang/go

by [email protected]:

Would it be possible to add a math.Round(n float64, digits uint) float64 function that
rounds a floating point number to the specified number of digits? This has been
discussed on golang-nuts here:
https://groups.google.com/d/topic/golang-nuts/ITZV08gAugI/discussion

I am not entirely convinced by the required digit argument. Perhaps we should have:

Round(n float64) float64 {
  return RoundDigits(n, 0)
}

Most helpful comment

For what it's worth, this (IMO injudiciously) closed ticket is the second result when you Google "how to round numbers in golang". Here's my vote for bringing this ticket back and adding a func Round(float64) float64 function to the math package.

All 25 comments

Comment 1:

What would this function be supposed to do?

Comment 2:

Floating point numbers don't have digits. 
The bar for being useful needs to be pretty high to be in the Go math package. We
accepted most of what's in the C library but we're not going to take all the routines
from other libraries. The Javascript round is a 1-liner: int(f+0.5).

_Status changed to WontFix._

Comment 3 by [email protected]:

Another option is to round half away from zero, so this would be:
if n < 0 {
  return math.Ceil(n-0.5)
}
return math.Floor(n+0.5)
This is arguably no less complex than math.Abs, although I assume the latter is in the
Go library due to its inclusion in the C library.
If I have some time I will code up a Go rounding module with different rounding
strategies.

Comment 4:

Some news about this Issue?

Comment 5:

The issue is marked "won't fix".

@rsc As a new gopher, not seeing a round function in the math package also tripped me up. The one-liner int(f+0.5) only works for positive values, which I assume is one reason JavaScript provides the Math.round() method to properly round numbers to the nearest integer.

I'd like to see this issue reconsidered, but in the meantime I'll use the following function. I'm only a new gopher, so I respect the core contributors' decision. But for those of us coming from Python, JavaScript, or Ruby, this may be a tripping hazard, albeit a small one.

func Round(val float64) int {
    if val < 0 {
        return int(val-0.5)
    }
    return int(val+0.5)
}

For those gophers wanting to round a float64 to a float64 with a given precision, here are two gists:

FYI, there is also a one-liner version of round(float64) int:
http://play.golang.org/p/iTYytKn6HA

func round(f float64) int {
return int(f + math.Copysign(0.5, f))
}

Unfortunately, math.Copysign couldn't be inlined by the
current gc implementation.

@minux Thanks for the info. I have much to learn about Go.

The function above breaks for 0.49999999999999997

Updated function: http://play.golang.org/p/m3d40AQVS6

func round(f float64) int {
    if math.Abs(f) < 0.5 {
        return 0
    }
    return int(f + math.Copysign(0.5, f))
}

Having seen at least 3 different people try to write a Round() function and fail in various ways (sometimes subtle, sometimes not so subtle like @rsc above suggesting to use int(f+0.5), which doesn't work for negative values), I do wonder why this isn't included in the math package. Sure, "the bar for being useful needs to be pretty high", but when most people don't get simple maths right... And this often needs to be both correct and fast.

@tsuna: I appreciate the sentiment. That said, I think it wouldn't be as simple as just adding a generic round function as there are many ways to round (the IEEE floating point standard defines a handful of modes; and int(f+0.5) is correct for one of them). It may indeed be better to leave this to the respective application which can choose to do the optimal thing.

You don't even need to use math.Abs and math.Copysign, I use:

func round(f float64) int {
    if f < -0.5 {
        return int(f - 0.5)
    }
    if f > 0.5 {
        return int(f + 0.5)
    }
    return 0
}

How about defining functions for all of the IEEE standard rounding modes?
On 20 Apr 2016 18:11, "Robert Griesemer" [email protected] wrote:

@tsuna https://github.com/tsuna: I appreciate the sentiment. That said,
I think it wouldn't be as simple as just adding a generic round function as
there are many ways to round (the IEEE floating point standard defines a
handful of modes; and int(f+0.5) is correct for one of them). It may
indeed be better to leave this to the respective application which can
choose to do the optimal thing.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
https://github.com/golang/go/issues/4594#issuecomment-212518844

Or a math/round package so you can say round.Method(f) instead of math.RoundMethod(f).

For that matter it could just as easily be a third party library, and probably should be—at the very least until it's complete, stabilized, well vetted, and judged idiomatic and generally useful.

Also nothing in this thread handles stuff like NaN or ±Inf, let alone regular floating point values that can't be stuffed into an int.

I feel like a basic round function would be very helpful. There is no need for every user of the language to have to build a round function (even if it is "trivial" to implement). Sound like an easy addition that would provide value.

For what it's worth, this (IMO injudiciously) closed ticket is the second result when you Google "how to round numbers in golang". Here's my vote for bringing this ticket back and adding a func Round(float64) float64 function to the math package.

We've added our own version of the utility in Kubernetes but it would be nice to see this in stdlib. Seems useful for many people.

How about defining functions for all of the IEEE standard rounding modes?

IEEE defines 5 rounding modes: TiesToEven, TiesToAway, TowardPositive, TowardNegative, TowardZero.

In the context of rounding an existing float value to a nearby integer value, TowardPositive, TowardNegative, and TowardZero are equivalent to package math's existing Ceil, Floor, and Trunc functions, respectively.

That leaves just TiesToEven and TiesToAway. It's not obvious to me that TiesToEven is useful in the context of integral rounding.

I believe there should be a simply way for rounding numbers.

@dsantosp12, this is a closed issue. Comments on closed issues are generally ignored.

Also, your comments adds nothing unique. See https://golang.org/wiki/NoMeToo

@bradfitz this implies you monitor closed issues for :+1: reactions. Do you do it at all? If so, how?

No, most people don't monitor, see, track, or follow-up on closed issues at all. None of our dashboards care about closed issues. I saw this email and replied, but most people don't get emails about them either.

To round a float to arbitrary precision, this decimal package could be helpful.

Why doesn't Go use the native instructions for rounding ?

@dansouza, see https://github.com/golang/go/issues/20100#issuecomment-313926393

You're replying to a closed issue from 2012 from when it was decided to not (yet) add Round to the standard library.

The issue you want to read is #20100 from 2017 which was approved and will be added to Go 1.10.

I'm going to lock this issue to focus attention to #20100.

Was this page helpful?
0 / 5 - 0 ratings