25

I'm getting numbers like

2.36363636363636
4.567563
1.234566465448465
10.5857447736

How would I get Ruby to round these numbers up (or down) to the nearest 0.05?

Andrew Marshall
  • 92,562
  • 20
  • 215
  • 211
dotty
  • 38,389
  • 65
  • 144
  • 195

9 Answers9

25
[2.36363636363636, 4.567563, 1.23456646544846, 10.5857447736].map do |x|
  (x*20).round / 20.0
end
#=> [2.35, 4.55, 1.25, 10.6]
sepp2k
  • 353,842
  • 52
  • 662
  • 667
  • Darn, you beat be me by a couple of seconds! +1 from me, although I had a slight different version in mind. – Swanand Aug 28 '09 at 10:58
  • This doesn't round UP to the nearest 0.05 as requested by OP, 2.36.... should be 2.40, not 2.35. – Christopher Maujean Apr 08 '12 at 23:40
  • 2
    @ChristopherMaujean True, but (despite the title) that's not what the OP asked for. The body of the question says "round these numbers up (**or down**) to the **nearest** 0.05". Anyway if you want to round up, use `ceil` instead of `round`. – sepp2k Apr 09 '12 at 12:34
  • I've edited the title to reflect the question, if I'm allowed, I'll remove my downvote. – Christopher Maujean Apr 11 '12 at 23:31
21

Check this link out, I think it's what you need. Ruby rounding

class Float
  def round_to(x)
    (self * 10**x).round.to_f / 10**x
  end

  def ceil_to(x)
    (self * 10**x).ceil.to_f / 10**x
  end

  def floor_to(x)
    (self * 10**x).floor.to_f / 10**x
  end
end
Smar
  • 7,223
  • 2
  • 34
  • 46
Damian
  • 1,533
  • 14
  • 22
  • 8
    Nice link. Answer would be better with a summary, though, so it can stand on it's own, especially since the linked code doesn't do exactly what the OP asks, i.e., round to the nearest 0.05, but rounds to a particular decimal place. – tvanfosson Aug 28 '09 at 11:00
  • 4
    And worse, b/c the post actually reimplements the built-in ruby function round(number-of-decimal-places), it's a bad idea. – Rob Apr 05 '12 at 14:32
  • 4
    downvote for only supplying a link, lame... and a link that doesn't even answer the question. – OpenCoderX May 24 '12 at 14:09
  • up vote since it does answer the question and round(x) isn't until ruby 0.9.6. – Aaron Turner Mar 07 '13 at 22:52
  • the monkey patching need not be necessary. the technique by multiplying by factor, applying_a_function, then dividing by same factor is what you need. Next quarter-currency_unit? use 4 as the factor and `ciel.to_f`... and so on... – Jerome Dec 10 '15 at 12:45
  • As other people have pointed out, this doesn't actually do what the question asks for... – philomory Mar 12 '17 at 02:00
  • The `ceil_to` function does not work consistently. For example, `0.07.ceil_to(2)` returns `0.08`, but SHOULD be `0.07`. The same occurs for 0.14, 0.28, 0.55, 1.09, etc. – jsmartt Apr 04 '18 at 15:43
19

In general the algorithm for “rounding to the nearest x” is:

round(x / precision)) * precision

Sometimes is better to multiply by 1 / precision because it is an integer (and thus it works a bit faster):

round(x * (1 / precision)) / (1 / precision)

In your case that would be:

round(x * (1 / 0.05)) / (1 / 0.05)

which would evaluate to:

round(x * 20) / 20;

I don’t know any Python, though, so the syntax might not be correct but I’m sure you can figure it out.

Bombe
  • 78,266
  • 20
  • 120
  • 125
11

less precise, but this method is what most people are googling this page for

(5.65235534).round(2)
#=> 5.65
boulder_ruby
  • 35,534
  • 9
  • 71
  • 93
  • 1
    5.6355.round(2) != 5.65, but TS wants 5.65 – Dmitry Lihachev Apr 11 '13 at 05:14
  • This solution only rounds the number to two decimal places, it does not return a rounded value to the nearest 0.05 as requested. – Scott Swezey May 02 '13 at 02:01
  • in some ways you're right, I should delete this answer. But on another level this is a very popular question that gets linked to in searches where people find this answer helpful, so I'm going to keep it visible – boulder_ruby Jul 05 '14 at 14:45
8

Here's a general function that rounds by any given step value:

place in lib:

lib/rounding.rb
class Numeric
  # round a given number to the nearest step
  def round_by(increment)
    (self / increment).round * increment
  end
end

and the spec:

require 'rounding'
describe 'nearest increment by 0.5' do
  {0=>0.0,0.5=>0.5,0.60=>0.5,0.75=>1.0, 1.0=>1.0, 1.25=>1.5, 1.5=>1.5}.each_pair do |val, rounded_val|
    it "#{val}.round_by(0.5) ==#{rounded_val}" do val.round_by(0.5).should == rounded_val end
  end
end

and usage:

require 'rounding'
2.36363636363636.round_by(0.05)

hth.

lfender6445
  • 29,844
  • 11
  • 111
  • 95
Rob
  • 4,324
  • 2
  • 30
  • 33
4

It’s possible to round numbers with String class’s % method.

For example

"%.2f" % 5.555555555

would give "5.56" as result (a string).

Smar
  • 7,223
  • 2
  • 34
  • 46
4

Ruby 2 now has a round function:

# Ruby 2.3
(2.5).round
 3

# Ruby 2.4
(2.5).round
 2

There are also options in ruby 2.4 like: :even, :up and :down e.g;

(4.5).round(half: :up)
 5
tokhi
  • 19,860
  • 23
  • 91
  • 104
2

To get a rounding result without decimals, use Float's .round

5.44.round
=> 5

5.54.round
=> 6
Fellow Stranger
  • 28,875
  • 31
  • 150
  • 214
0

I know that the question is old, but I like to share my invention with the world to help others: this is a method for rounding float number with step, rounding decimal to closest given number; it's usefull for rounding product price for example:

def round_with_step(value, rounding)
  decimals = rounding.to_i
  rounded_value = value.round(decimals)

  step_number = (rounding - rounding.to_i) * 10
  if step_number != 0
    step = step_number * 10**(0-decimals)
    rounded_value = ((value / step).round * step)
  end

  return (decimals > 0 ? "%.2f" : "%g") % rounded_value
end

# For example, the value is 234.567
#
# | ROUNDING | RETURN | STEP
# | 1        | 234.60 | 0.1
# | -1       | 230    | 10
# | 1.5      | 234.50 | 5 * 0.1 = 0.5
# | -1.5     | 250    | 5 * 10  = 50
# | 1.3      | 234.60 | 3 * 0.1 = 0.3
# | -1.3     | 240    | 3 * 10  = 30
bimlas
  • 2,009
  • 1
  • 19
  • 28