Ruby 2.4 will be merging both Fixnum
& Bignum
into the same class (Integer
) so I think this is a good time to review the different number types in Ruby!
And that’s what we are going to talk about in this post ðŸ™‚
An Overview of Number Types
Let’s start by taking a look at the class hierarchy of all the number related classes in Ruby:

Numeric Integer Fixnum Bignum Float Complex Rational BigDecimal (Standard Library) 
As you can see, the Numeric
class is the parent for all the number classes. Remember that you can use the ancestors
method to discover the parent classes for any class.
Example:

Fixnum.ancestors  Fixnum.included_modules [Fixnum, Integer, Numeric, Object, BasicObject] 
Now let’s see these classes in table form:
Class 
Description 
Example 
Fixnum 
Normal numbers that fit into the OS integer type 
1 
Bignum 
Used for bigger numbers 
111111111111 
Float 
Imprecise decimal numbers 
5.0 
Complex 
Used for math stuff with imaginary numbers 
(1+0i) 
Rational 
Used to represent fractions 
(2/3) 
BigDecimal 
Perfect precision decimal numbers 
3.0 
Float Imprecision
You may have noticed that in the description for the Float
class it says “imprecise”, what’s the meaning of that?
Let me show you with an example:
Why is this false? Let’s look at the result of 0.2 + 0.1
.
And that’s what I mean by imprecision! The reason this happens is because of the way that a float is stored. If you need decimal numbers that are always accurate you can use the BigDecimal
class.
Example:

require 'bigdecimal' BigDecimal("0.2") + BigDecimal("0.1") == 0.3 # true 
Why don’t we always use BigDecimal
then? Because it’s a lot slower!
Here is a benchmark:

Calculating  bigdecimal 21.559k i/100ms float 79.336k i/100ms  bigdecimal 311.721k (Â± 7.4%) i/s  1.552M float 3.817M (Â±11.7%) i/s  18.803M Comparison: float: 3817207.2 i/s bigdecimal: 311721.2 i/s  12.25x slower 
BigDecimal
is 12 times slower than Float
, and that’s why it’s not the default ðŸ™‚
Fixnum vs Bignum
In this section I want to explore the differences between Fixnum
and Bignum
.
Let’s start with some code:

1.class # Fixnum 100000000000.class # Bignum 
Ruby creates the correct class for us, and it will automatically promote a Fixnum
to a Bignum
when necessary.
Note: You may need a bigger number to get a Bignum
object if you have a 64bit Ruby interpreter.
Why do we need different classes? The answer is that to work with bigger numbers you need a different implementation, and working with big numbers is slower, so we end up with a similar situation to Float
vs BigDecimal
.
The Fixnum
class also has some special properties. For example, the object id is calculated using a formula.

1.object_id # 3 20.object_id # 41 
The formula is: (number * 2) + 1
.
But there is more to this, when you use a Fixnum
there is no object being created at all. There is no data to store in a Fixnum
, because the value is derived from the object id itself. This is just an implementation detail, but I think it’s interesting to know ðŸ™‚
MRI (Matz’s Ruby Interpreter) uses these two macros to convert between value & object id:

INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1  FIXNUM_FLAG)) FIX2LONG(x) ((long)RSHIFT((SIGNED_VALUE)(x),1)) 
What happens here is called “bit shifting”, which moves all the bits to the left or the right. Shifting one position to the left is equivalent to multiplying by 2 & that’s why the formula is (number * 2) + 1
. The +1 comes from the FIXNUM_FLAG
.
In contrast, Bignum
works more like a normal class & uses normal object ids:

111111111111111.object_id # 23885808 
All this means is that Fixnum
objects are closer to symbols in terms of how they work at the interpreter level, while Bignum
objects are closer to strings.
Summary
In this post you learned about the different numberrelated classes that exist in Ruby.
You learned that floats are imprecise, and that you can use BigDecimal
if accuracy is a lot more important than performance. And after that you learned that Fixnum
objects are special at the interpreter level, but Bignum
s are just regular objects.
If you found this post interesting don’t forget to signup to my newsletter in the form below ðŸ™‚