Infinity
This is hardly an original trick (it’s been mentioned many times before, on countless other blogs) but it is useful enough that it deserves mention yet again.
Ruby won’t let you divide an integer by zero—you’ll get an exception. However, thanks to the IEEE 754 standard for floating point numbers, when you try to divide a float by zero you get a rather special value back:
1 2 |
puts 1.0/0 #-> Infinity |
It’s not a constant though, it’s just how that floating point result is represented as a string. However, you can easily assign that value to a constant:
1 |
Infinity = 1.0/0 |
Once you have that, you can use it for all kinds of nifty things; throw it in ranges, use it in comparisons, whatever suits your fancy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# a rather useless range everything = -Infinity..Infinity puts everything.include?(5) #-> true # use it for representing an unbounded value storage_limits => { :demo => 0, :standard => 250.megabytes, :expert => 1.gigabyte, :unlimited => Infinity } if bytes_used < storage_limits[account_level] # add another file or something else # display "out of space" message end |
Like I said earlier, it’s old news, but no less handy for that.
Reader Comments
A RCR for this has been added to 1.9/2.0, fwiw:
http://rcrchive.net/rcrs/5
7 Feb 2007
Cool! This blog is a great resource :)
7 Feb 2007
Shouldn’t it rather be “include?(5)” ?
7 Feb 2007
It would be great if this worked within conditions for find method. Like this:
User.find :all, :conditions => {:height => 150..Infinity}
8 Feb 2007
Michael, you’re right, my bad. I’ve corrected the article.
Bobes, I think it’s clearer to just say “height >= 150”. The intention is more manifest, and it’s even fewer characters to type. :)
8 Feb 2007
Nice!
I have stumbled on to this before, and couldn;t figure out why sometimes I would get a
ZeroDivisionError
and sometimes I would getInfinity
. I was even more confused whenInifinity
was an uninitialized constant.For clarification, an integer divided by zero gives you an error, where a float divided by zero gives
Infinity
.Thanks for not only helping me sort that out but also show how useful it is.
8 Feb 2007
I never understood the incongruity in the way a float zero acts vs any other float vs an integer float. I can understand Infinity as a result and I can understand 0 as a result, but NaN for this one case?
9 Feb 2007
Wes, it’s the way that operation is defined. Mathematically speaking, dividing any positive, non-zero value by zero will give you an infinitely large number (you can prove this with limits; dividing some number by smaller and smaller numbers, you get larger and larger quotients). Also, mathematically, dividing any zero by any non-zero value will give you zero. However, zero divided by itself is undefined—it is not a number, and so you get NaN when you try to do so on a computer.
9 Feb 2007
Interesting, is there anyway to encode the concept of Infinity in a database? Looking at your example for storage_limits, it appeared to be possible. (1.0/0).class => Float, so I tried creating a record in a mysql table with a float field => Infinity thinking it would do some kind of magic value, but ActiveRecord turned Infinity into an unescaped string in the sql call.
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column ‘Infinity’ in ‘field list’: INSERT INTO bill_payments (`bill_id`, `paid_bill_id`, `payment`, `is_deleted`) VALUES
Ok, maybe a bad example, I’d like to see someone pay an infinite bill ;)
13 Feb 2007