ruby picture

RCR 302: Rounding Accuracy

Submitted by transami (Tue Apr 19 23:26:21 UTC 2005)

Abstract

Add an argument to #round to specify rounding accuracy.

Problem

Currently Float#round (as well as the realted Numeric and Integer method) do not allow for any specification of accuracy, but rather rounds only to the nearest integer.

Proposal

Add an optional argument to #round to allow for the specification of accuracy.

Since #round currently takes no arguments there should be no backward compatibility issues. The only catch to consider is that #round returns an Integer without an argument, but would return a Float with one. This isn't an issue as much as it is something to note.

Analysis

Rounding to specific accuracies, common to finacial and mathematically inclined scripts, becomes much easier with this support.

Implementation

There are few ways to allow this functionality. One way is via the powers of ten:

  #   4.555.round(0)  #=> 5.0
  #   4.555.round(1)  #=> 4.6
  #   4.555.round(2)  #=> 4.56
  #   4.555.round(3)  #=> 4.555
  alias :round_off :round
  def round( d=0.0 )
    (self * (10.0 ** d)).round_off.to_f / (10.0 ** d)
  end

Another is to the nth degree:

  #   4.555.round(1)     #=> 5.0
  #   4.555.round(0.1)   #=> 4.6
  #   4.555.round(0.01)  #=> 4.56
  #   4.555.round(0)     #=> 4.555
  alias :round_off :round
  def round( n )
    return self if n == 0
    (self * (1.0 / n)).round_off.to_f / (1.0 / n)
  end

Or one could specify the rounding factor directly:

  #   4.555.round(1)     #=> 5.0
  #   4.555.round(10)    #=> 4.6
  #   4.555.round(100)   #=> 4.56
  #   4.555.round(1000)  #=> 4.555
  alias :round_off :round
  def round( a=1.0 )
    (self * a).round_off.to_f / a
  end
ruby picture
Comments Current voting
Of these, I prefer the first. Many moons ago, when I was still taking science courses, the emphasis was on significant digits. If I could measure 2.54 exact, then I could have three significant digits. If I could only measure 2.5, then I could only have two significant digits. (Thus, 3 * 2.54 would have one significant digit, or approximately 9. 3.00 * 2.54 would have three significant digits.)

The science form rounded a bit more aggressively -- e.g., if I have one significant digit and the value 11, my rounded value would be 10. But if we cast the #round argument in terms of significant decimal places, then this makes perfect sense.


-- good idea, its useful


I think this was discussed on #ruby-lang at some point... I like the proposal as such, but to my non-mathematical brain the simplest form would be to signal how many significant digits there will be. If you allow my fancy, how about marking the significant digits with the method/method_missing #o...?

 5.454534442.round.ooo # 5.454
 5.453534442.round.OO  # 5.45

The other urge is to support rounding to the 'nearest something' for Fixnums/Integers, too:

 998.round(1000)  # 1000
 2543.round(1000) # 3000 

-esaynatkari


I'm slightly concerned that this would be (ab)used for formatting of values, which would not work reliably due to the (well-known) floating point arithmetic "issues".


In favor of the first option. It also gives you the ability to specify negative decimal places, to round to the nearest 10, 100, etc.

Users would quickly find out that it was NOT for string formatting, and learn to use (or wrap) sprintf accordingly.


Strongly opposed 0
Opposed 0
Neutral 0
In favor 6
Strongly advocate 6
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .