opensoul.org

Round floats to the nearest X

For those pesky times when whole numbers just won’t cut it, but you only want some precision.

7.7.round(0.5)   #=> 7.5
7.95.round(0.5)  #=> 8
8.2.round(1.5)   #=> 7.5
8.3.round(1.5)   #=> 9

The magic, courtesy of Daniel Morrison:

class Float
  def round(round_to = 1.0)
    mod = self % round_to
    rounded = self - mod + (mod >= round_to/2.0 ? round_to : 0)
    rounded % 1 == 0 ? rounded.to_i : rounded
  end
end

Note that do to some quirks with Ruby’s handling of floats, you won’t get what you expect in some situations:

3.5.round(0.2)   #=> 3.4, instead of 3.6

core_ext, float, and ruby July 18, 2007

4 Comments

  1. Matt Jones Matt Jones July 18, 2007

    This is a little more complicated, but it correctly rounds
    results:

    class Float
      alias_method :old_round, :round unless method_defined?(:old_round)
      def round(round_to = 1.0)
        scaled = self / round_to
        rounded = scaled.old_round * round_to
        rounded % 1 == 0 ? rounded.to_i : rounded
      end
    end
    
  2. Dan Kubb Dan Kubb December 6, 2007

    What about:

    require 'bigdecimal'
    
    class Float
      def round(to = 0)
        rounded = BigDecimal(self.to_s).round(to)
        to == 0 ? rounded.to_i : rounded
      end
    end
    
  3. ojak ojak June 29, 2010

    For what it’s worth… matt’s benchmark’ed as the quickest:

    user system total real

    mjones 0.260000 0.010000 0.270000 ( 0.283507)
    original 0.330000 0.010000 0.340000 ( 0.362051)
    dkubb 0.700000 0.010000 0.710000 ( 0.717374)

  4. ojak ojak June 29, 2010

    For what it’s worth… matt’s benchmark’ed as the quickest:

                                user     system      total        real
    mjones       0.260000   0.010000   0.270000 (  0.283507)
    original       0.330000   0.010000   0.340000 (  0.362051)
    dkubb         0.700000   0.010000   0.710000 (  0.717374)
    

My name is Brandon Keepers. I like to build things, usually in Ruby or JavaScript. I work at GitHub and live in Holland, MI.

Popular Posts