Rounding float in ruby via .round

Discussion in 'Ruby' started by Marc Heiler, Jan 2, 2010.

  1. Marc Heiler

    Marc Heiler Guest

    round does not want arguments. Is there a reason why not?

    Ok, we can easily have workarounds by extending class Float. Or using
    another strategy.

    http://www.hans-eric.com/code-samples/ruby-floating-point-round-off/

    But it made me actually wonder - is there a reason why .round does not
    want any arguments?

    My brain would easily tell me that I would expect

    2.29801801942891420890142890124.round(3)

    to become 2.298

    Is this not possible because it would become a different object?
    --
    Posted via http://www.ruby-forum.com/.
    Marc Heiler, Jan 2, 2010
    #1
    1. Advertising

  2. On 02.01.2010 02:43, Marc Heiler wrote:
    > .round does not want arguments. Is there a reason why not?


    Hmmm..

    irb(main):001:0> RUBY_VERSION
    => "1.9.1"
    irb(main):002:0> 3.14567534.round
    => 3
    irb(main):003:0> 3.14567534.round 3
    => 3.146
    irb(main):004:0> 3.14567534.class
    => Float

    Which Ruby are you on?

    --
    Phillip Gawlowski
    Phillip Gawlowski, Jan 2, 2010
    #2
    1. Advertising

  3. Marc Heiler

    pharrington Guest

    On Jan 1, 9:13 pm, Phillip Gawlowski <> wrote:
    > Which Ruby are you on?


    <= 1.8.7
    pharrington, Jan 2, 2010
    #3
  4. pharrington wrote:
    > On Jan 1, 9:13�pm, Phillip Gawlowski <> wrote:
    >> Which Ruby are you on?

    >
    > <= 1.8.7


    It shouldn't be too hard to write that behavior into 1.8.7...

    Best,
    --
    Marnen Laibow-Koser
    http://www.marnen.org

    --
    Posted via http://www.ruby-forum.com/.
    Marnen Laibow-Koser, Jan 2, 2010
    #4
  5. Marc Heiler

    Phrogz Guest

    On Jan 1, 7:22 pm, pharrington <> wrote:
    > On Jan 1, 9:13 pm, Phillip Gawlowski <> wrote:
    >
    > > Which Ruby are you on?

    >
    > <= 1.8.7


    You could do (untested on 1.8):

    if Float.instance_method:)round).arity == 0
    class Float
    alias_method :_orig_round, :round
    def round( decimals=0 )
    factor = 10**decimals
    (self*factor)._orig_round / factor
    end
    end
    end

    Even gives you rounding to 'negative' decimal places, as in 1.9
    Phrogz, Jan 2, 2010
    #5
  6. Marc Heiler

    Phrogz Guest

    On Jan 1, 9:32 pm, Phrogz <> wrote:
    > On Jan 1, 7:22 pm, pharrington <> wrote:
    >
    > > On Jan 1, 9:13 pm, Phillip Gawlowski <> wrote:

    >
    > > > Which Ruby are you on?

    >
    > > <= 1.8.7

    >
    > You could do (untested on 1.8):
    >
    > if Float.instance_method:)round).arity == 0
    >   class Float
    >     alias_method :_orig_round, :round
    >     def round( decimals=0 )
    >       factor = 10**decimals
    >       (self*factor)._orig_round / factor
    >     end
    >   end
    > end
    >
    > Even gives you rounding to 'negative' decimal places, as in 1.9


    Note that this gives you a Float as the result, which you may need to
    use sprintf to display as desired. If you want something like
    JavaScript's toFixed(), returning a string certain to be displaying
    the precision you wanted, you might instead do (also untested):

    class Numeric
    def round_to_str( decimals=0 )
    if decimals >= 0
    "%.#{decimals}f" % self
    else
    factor = 10**-decimals
    ((self/factor).round * factor).to_s
    end
    end
    end
    Phrogz, Jan 2, 2010
    #6
  7. Marc Heiler

    Phrogz Guest

    On Jan 1, 9:32 pm, Phrogz <> wrote:
    > You could do (untested on 1.8):
    >
    > if Float.instance_method:)round).arity == 0
    >   class Float
    >     alias_method :_orig_round, :round
    >     def round( decimals=0 )
    >       factor = 10**decimals
    >       (self*factor)._orig_round / factor
    >     end
    >   end
    > end


    Bah, should have tested. Of course the original round returns a
    fixnum, so dividing by the factor at that point really doesn't do what
    I had intended.

    Here are a few alternatives. Poke fun at them and/or benchmark as you
    see fit:

    if Float.instance_method:)round).arity == 0
    class Float
    alias_method :_orig_round, :round
    def round( decimals=0 )
    factor = 10.0**decimals
    (self*factor)._orig_round / factor
    end
    end
    end

    if Float.instance_method:)round).arity == 0
    class Float
    alias_method :_orig_round, :round
    def round( decimals=0 )
    factor = 10**decimals
    (self*factor)._orig_round.to_f / factor
    end
    end
    end

    if Float.instance_method:)round).arity == 0
    class Float
    alias_method :_orig_round, :round
    def round( decimals=0 )
    factor = 10**decimals
    (self*factor)._orig_round / factor.to_f
    end
    end
    end
    Phrogz, Jan 2, 2010
    #7
  8. On Sat, Jan 2, 2010 at 2:13 AM, Phillip Gawlowski <> wrote:
    > Hmmm..
    > irb(main):001:0> RUBY_VERSION #=> "1.9.1"
    > irb(main):002:0> 3.14567534.round #=> 3
    > irb(main):003:0> 3.14567534.round 3 #=> 3.146


    I didn't know 1.9 had extended Float#round. That's useful. Thank you
    for the information.

    But I'm not sure that Float#round should be allowed to have
    non-integer arguments:

    # IRB Ruby 1.9.1
    n = 9876.54321
    f = 1.75
    r = Rational(7, 4) #=> (7/4)
    c = Complex(f, 0) #=> (1.75+0i)
    ci = Complex(f, 2) #=> (1.75+2i)
    n.round #=> 9877
    n.round 0 #=> 9877
    n.round -1 #=> 9880
    n.round 1 #=> 9876.5
    n.round f #=> 9876.5
    n.round r #=> 9876.5
    n.round c #=> 9876.5
    n.round ci # RangeError: can't convert 1.75+2i into Integer

    # it's nice that Integer#round is consistent with Float#round
    i = 9876
    i.round #=> 9876
    i.round 0 #=> 9876
    i.round -1 #=> 9880
    i.round 1 #=> 9876.0

    # Rational#round: an opportunity for someone?
    r = 9876 + Rational( 54321, 100000 ) #=> (987654321/100000)
    r.to_f #=> 9876.54321
    r.round #=> 9877
    r.round 1 # ArgumentError: wrong number of arguments(1 for 0)
    Colin Bartlett, Jan 2, 2010
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. bd
    Replies:
    0
    Views:
    597
  2. Fuzzydave

    round not rounding to 0 places

    Fuzzydave, Aug 16, 2006, in forum: Python
    Replies:
    6
    Views:
    381
    Sybren Stuvel
    Aug 16, 2006
  3. Carsten Fuchs
    Replies:
    45
    Views:
    1,486
    James Kanze
    Oct 8, 2009
  4. OliverMarchand

    Float.round - should it be round-to-even

    OliverMarchand, Apr 12, 2006, in forum: Ruby
    Replies:
    2
    Views:
    206
    OliverMarchand
    Apr 12, 2006
  5. ddoherty03
    Replies:
    4
    Views:
    92
    ddoherty03
    Jul 23, 2009
Loading...

Share This Page