Infinity

Posted by Jamis on February 07, 2007 @ 09:36 AM

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.

Posted in Tips & Tricks

Comments

Have something to add? Click here to leave a comment.

07 Feb 2007

1. Anonymous Cow said...

A RCR for this has been added to 1.9/2.0, fwiw:

http://rcrchive.net/rcrs/5

2. coder_ said...

Cool! This blog is a great resource :)

3. Michael Marzec said...

Shouldn’t it rather be “include?(5)” ?

08 Feb 2007

4. bobes said...

It would be great if this worked within conditions for find method. Like this:

User.find :all, :conditions => {:height => 150..Infinity}

5. Jamis said...

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. :)

6. Alex Wayne said...

Nice!

I have stumbled on to this before, and couldn;t figure out why sometimes I would get a ZeroDivisionError and sometimes I would get Infinity. I was even more confused when Inifinity 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.

09 Feb 2007

7. Wes said...

1
2
3
4
5
6
7
8
9

1.0/0
=> Infinity

0.0/0
=> NaN

0/1
=> 0

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?

8. Jamis said...

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.

13 Feb 2007

9. Tony Buser said...

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 ;)