# Adding utility to core classes

by Caleb Tennis

I have a small repository of utility code that almost all of my Ruby projects require because I find them so beneficial to what I do. One such function is a quick precision hack for the Float class. Here's the code:

```
class Float
def prec(x)
sprintf("%.0" + x.to_i.to_s + "f", self).to_f
end
end
```

This is nice, because it allows you to quickly round a float to a certain decimal value without having to resort to much trickery.

```
irb> i = 100.0 / 9.4
=> 10.6382978723404
irb> i.prec(2)
=> 10.64
```

It did get me thinking though: is there a smarter way of implementing this method?

We can get rid of the sprintf and just use the % method.

```
class Float
def prec(x)
(("%.0" + x.to_i.to_s + "f") % self).to_f
end
end
```

It still seems to me like that code could be simplified even further. Do any of you have any ideas how to make it any more compact?

 James Edward Gray II 2005-12-20 12:18:23 `````` class Float def prec(x) ("%.0#{x.to_i}f" % self).to_f end end `````` Looks a little less noisy to me. James Edward Gray II Ryan Leavengood 2005-12-20 12:31:42 I'll second James, as that is exactly what I was going to post. Jonas 2005-12-20 14:10:49 What about: class Float def prec(x) (self * 10**x).to_i / (10**x).to_f end end Brian Buckley 2005-12-20 19:59:05 An advantage (I think) of Jonas' solution is it allows rounding on the other side of the decimal when x is negative. 1234.567.prec(-2) #=>1200.0 Also why not put prec into Numeric instead of Float? Question: On Caleb's, James' and Ryan's solutions, why are we calling to_i on x? Doesn't x have to be an integer anyway for prec to work properly? Thanks in advance for explaining. fansipans 2005-12-21 12:40:51 34 characters: (self * 10**x).to_i / (10**x).to_f 29 characters: ("%.0#{x.to_i}f" % self).to_f in the spirit of a good game of golf, my stab at it: 19 characters: to_s[/.*\..{#{x}}/] can't you leave off the final .to_f since coercion should take care of any type discrepancy? fansipans 2005-12-21 12:58:24 to_s[/.*\..{#{x}}/] 19 characters! Ahh... line noise in ruby ;D Ryan Leavengood 2005-12-21 13:12:15 Hi Brian, Our use of to_i is "Duck Typing" at work. If whatever is passed in can respond to to_i, we will have an integer. So whether the parameter is a String, a Fixnum, a Float or anything else that responds to to_i, it can be used. If it cannot be converted, an error will be thrown. Ryan Bates 2005-12-21 14:04:57 I have been using these three methods: ``` 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 ``` I wish the round, floor, and ceil methods allowed an optional precision argument. Aristotle Pagaltzis 2005-12-21 16:19:02 This should work: ``````class Float     def prec( x )         sprintf( "%.*f", x, self ).to_f     end end `````` Which is about as simple as I'd want it to be; any less would be obfuscatory. (Unless maybe Ruby's `printf` is dumbed down compared to the one I know from C and Perl; I wouldn't know.)