# Doubling numbers with Object#object\_id

**URL:** <https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327>\
**Category:** Ruby\
**Created:** [August 25, 2009, 8:07am UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327 "2009-08-25T08:07:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [August 25, 2009, 8:07am UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/1 "2009-08-25T08:07:09Z")

</div>

I was playing with Ruby and wrote an interesting method:

```
def double n
  n.object_id - 1
end

irb> double 5
  => 10
irb> double 1
  => 2
irb> double 0
  => 0
irb> double -101
  => -202
irb> double 100000001
  => 200000002
irb> double 10000000000 # into Bignum territory now
  => -606548539

```

Anyone know why this works? Why Ruby was implemented this way?

I tried creating an object\_id collision based on this doubling rule,  
but it seems that all Fixnum object\_id`s are odd, and all other object_id`s are even (in fact they all seem to end in 8). Clever.

---

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [August 25, 2009, 8:24am UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/2 "2009-08-25T08:24:45Z")

</div>

AFAIK, FixNums are implemented as direct values and not C structs that  
represent objects. Small integers - which means integers that can be  
held in (sizeof(unsigned long int) \* 8 -1 = 31 bits). 1 bit is used  
for sign and 30 bits for the value.

Here is the INT2FIX macro from Ruby source:  
#define INT2FIX(i) ((VALUE)(((long)(i))\<\<1 | FIXNUM\_FLAG))

Shift 1 bit to the left, and bitwise OR it with 1. In other words,  
object\_id = 2n + 1. That explains why your double method works.

cheers  
nilesh

---

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [August 25, 2009, 8:27am UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/3 "2009-08-25T08:27:40Z")

</div>

All other Ruby objects are allocated on addresses that are multiples  
of 4 to avoid clash with FixNum. So Object ID is always even for them.

cheers  
nilesh

---

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [August 25, 2009, 8:59am UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/4 "2009-08-25T08:59:56Z")

</div>

Aah that explains everything, thankyou. That’s a very beautiful  
system. Makes me want to design my own interpreter and take part in  
such things.

---

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [August 27, 2009, 12:22am UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/5 "2009-08-27T00:22:44Z")

</div>

EbFFA:

> I was playing with Ruby and wrote an interesting method:

> ```
> def double n
> n.object_id - 1
> end
> 
> ```

> Anyone know why this works? Why Ruby was implemented this way?

Note that other Ruby implementations (JRuby, Rubinius, IronRubyâ€¦) do  
not have to keep this contract; itâ€™s best considered as MRI peculiarity.  
But yes, I do find this design beautiful â€“ as well as Rubyâ€™s method  
lookup: [http://www.viddler.com/explore/CobyR/videos/1/](http://www.viddler.com/explore/CobyR/videos/1/)

â€” Shot

---

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [September 3, 2009, 5:55pm UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/6 "2009-09-03T17:55:01Z")

</div>

On Wed, Aug 26, 2009 at 5:21 PM, Shot (Piotr S.)[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Note that other Ruby implementations (JRuby, Rubinius, IronRubyâ€¦) do  
> not have to keep this contract; itâ€™s best considered as MRI peculiarity.  
> But yes, I do find this design beautiful â€“ as well as Rubyâ€™s method  
> lookup: [http://www.viddler.com/explore/CobyR/videos/1/](http://www.viddler.com/explore/CobyR/videos/1/)

I don’t know that it’s particularly beautiful; it’s just a side effect  
of Fixnums not having any internal state and not actually being  
objects in MRI. Because they are “immediates” they don’t actually have  
an object\_id. As a result, their object\_id is just based on their  
actual value, 2n+1. All other objects then get stuffed into the  
remaining even object\_ids, and fixnum.object\_id - 1 == fixnum \* 2.

- Charlie

---

<div class="post-metadata">

**Author:** ![EbFFA](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/e/bcef8e/32.png) [@EbFFA](https://www.ruby-forum.com/u/EbFFA)\
**Post date:** [September 3, 2009, 6:38pm UTC](https://www.ruby-forum.com/t/doubling-numbers-with-object-object-id/174327/7 "2009-09-03T18:38:57Z")

</div>

On Thu, Sep 3, 2009 at 11:54 AM, Charles Oliver  
Nutter[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > 
> 
> remaining even object\_ids, and fixnum.object\_id - 1 == fixnum \* 2.  
> And its not that particularly unique to MRI. I know lots of VM  
> implementations for various languages (Ruby, Smalltalk, JavaScript  
> …) which use different variations of representing an integer n  
> smaller than 2\*\*b for some b less than the word length as:

```
  n * 2**flag_shift + int_flag

```

where flag\_shift is some small integer (usually but not always 1) and  
int\_flag is usually 1 or at least odd, since on most machines a  
pointer to an object will be aligned on some even address boundary.

For some reason, Googles V8 JavaScript VM uses an int\_flag of 1 and  
SETs the low order bit of references which are pointers, at least  
according to a video I watched about the implementation.

–  
Rick DeNatale

Blog: [http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)  
Twitter: [http://twitter.com/RickDeNatale](http://twitter.com/RickDeNatale)  
WWR: [http://www.workingwithrails.com/person/9021-rick-denatale](http://www.workingwithrails.com/person/9021-rick-denatale)  
LinkedIn: [http://www.linkedin.com/in/rickdenatale](http://www.linkedin.com/in/rickdenatale)
