integers and floats

R

Rajinder Yadav

Can someone explain to me why Ruby treats integers and floating point
numbers differently?

irb(main):069:0> 12.equal? 12
=> true

irb(main):071:0> 12.0.equal? 12.0
=> false

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely
 
B

botp

Can someone explain to me why Ruby treats integers and floating point
numbers differently?

irb(main):069:0> 12.equal? 12
=> true

irb(main):071:0> 12.0.equal? 12.0
=> false


ri Object#equal?

try eg,
=> true

kind regards -botp
 
P

Paul Smith

Can someone explain to me why Ruby treats integers and floating point
numbers differently?

irb(main):069:0> 12.equal? 12
=> true

irb(main):071:0> 12.0.equal? 12.0
=> false

Because they're different :)

With .equal you're checking to see whether 2 objects are in fact the
same object. 12, a Fixnum, is an immediate object, meaning all the
12s in your code are in fact the exact same object.

12.0, a floating point number, is constructed from scratch each time
you refer to it. So the 12.0 on the left is a separate construction
from the the 12.0 on the right.

irb(main):008:0> 12.object_id
=> 25
irb(main):009:0> a = 12
=> 12
irb(main):010:0> b = 12
=> 12
irb(main):011:0> a.object_id
=> 25
irb(main):012:0> b.object_id
=> 25

All of these 12's are the same object.

irb(main):013:0> 12.0.object_id
=> 11121408
irb(main):014:0> a = 12.0
=> 12.0
irb(main):015:0> b = 12.0
=> 12.0
irb(main):016:0> a.object_id
=> 11187424
irb(main):017:0> b.object_id
=> 10954912

All of these 12.0s are different objects

irb(main):018:0> 12 == 12
=> true
irb(main):019:0> 12.0 == 12.0
=> true

But all of the 12.0s have the same value.

The same distinction happens for symbols and strings:

irb(main):020:0> "abc".equal? "abc"
=> false
irb(main):021:0> :abc.equal? :abc
=> true
 
S

Stefano Crocco

|Can someone explain to me why Ruby treats integers and floating point
|numbers differently?
|
|irb(main):069:0> 12.equal? 12
|=> true
|
|irb(main):071:0> 12.0.equal? 12.0
|=> false

equal? returns true if two objects are the same, that is if they have the same
object_id. Integers represented by the Fixnum class are created only once: if
I write
x = 123456
y = 123465
ruby will create an instance of class Fixnum representing the number 123456 in
the first line, but in the second line it doesn't create a new one and simply
uses the one which already exists. This is the same thing which happens for
symbols.

On the other hand, the same doesn't happen for objects of class Float: here a
different instance is created every time:
x = 123.456
y = 123.456
produces two different objects representing the same floating point number.
You can check this looking at the object_id of the different objects.

I hope this helps

Stefano
 
R

Rajinder Yadav

Paul said:
Because they're different :)

thanks, I understand the object_id

my question is why is 12.0 constructed each time and 12 is immediate?
does it have to do with the fact that floats are simply binary
approximation.
With .equal you're checking to see whether 2 objects are in fact the
same object. 12, a Fixnum, is an immediate object, meaning all the
12s in your code are in fact the exact same object.

12.0, a floating point number, is constructed from scratch each time
you refer to it. So the 12.0 on the left is a separate construction
from the the 12.0 on the right.

irb(main):008:0> 12.object_id
=> 25
irb(main):009:0> a = 12
=> 12
irb(main):010:0> b = 12
=> 12
irb(main):011:0> a.object_id
=> 25
irb(main):012:0> b.object_id
=> 25

All of these 12's are the same object.

irb(main):013:0> 12.0.object_id
=> 11121408
irb(main):014:0> a = 12.0
=> 12.0
irb(main):015:0> b = 12.0
=> 12.0
irb(main):016:0> a.object_id
=> 11187424
irb(main):017:0> b.object_id
=> 10954912

All of these 12.0s are different objects

irb(main):018:0> 12 == 12
=> true
irb(main):019:0> 12.0 == 12.0
=> true

But all of the 12.0s have the same value.

The same distinction happens for symbols and strings:

irb(main):020:0> "abc".equal? "abc"
=> false
irb(main):021:0> :abc.equal? :abc
=> true


--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely
 
P

Paul Smith

thanks, I understand the object_id

my question is why is 12.0 constructed each time and 12 is immediate? doe= s
it have to do with the fact that floats are simply binary approximation.

I'm not sure how you would make floating point numbers immediate.

Fixnums can be immediate by a clever trick with the object_id. This
is done presumably for performance - application deal with small
integers all the time.

Is anything else an immediate object in this sense?

Symbols aren't immediate, but they have been made (presumbaly through
some kind of symbol table lookup) such that every :abc is the same
symbol.

I don't think anything else works this way either, symbols have a
particular use case that is different to strings, and Ruby can play
with both.

Could you make floats work the same way as symbols? Probably. Is it
worth it? Under what use case is it important that all 12.0s be the
exact same object?
--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely



--=20
Paul Smith
http://www.nomadicfun.co.uk

(e-mail address removed)
 
R

Rajinder Yadav

Paul said:
I'm not sure how you would make floating point numbers immediate.

Fixnums can be immediate by a clever trick with the object_id. This
is done presumably for performance - application deal with small
integers all the time.

Is anything else an immediate object in this sense?

Symbols aren't immediate, but they have been made (presumbaly through
some kind of symbol table lookup) such that every :abc is the same
symbol.

I don't think anything else works this way either, symbols have a
particular use case that is different to strings, and Ruby can play
with both.

Could you make floats work the same way as symbols? Probably. Is it
worth it? Under what use case is it important that all 12.0s be the
exact same object?

I don't know how Ruby makes integers immediate or why this is not
possible with floats. So to answer your use case question, the only use
case I see is the same one for integer. Efficiency of not having to
create new objects each time.

However I am going to assume trying to make floats immediate *is* less
efficient than creating new objects? or is there another reason floats
are treated the way they are in Ruby?
 
R

Robert Klemme

2009/12/22 Paul Smith said:
I'm not sure how you would make floating point numbers immediate.

Well, you could - but at the expense of dramatically increased memory
need for every Ruby program because a standard float needs more bytes
to store than an int and so every object reference would have to be
significantly larger.

http://en.wikipedia.org/wiki/Tagged_pointer

Plase see also the other current thread "Ruby's implementation of
Fixnum-assignment".
Fixnums can be immediate by a clever trick with the object_id. =A0This
is done presumably for performance - application deal with small
integers all the time.

It's rather the other way round: making Fixnums immediate is the
clever trick and Fixnum's object_id is a derivative of that trick.
Is anything else an immediate object in this sense?

AFAIK nil, true, false.
Symbols aren't immediate, but they have been made (presumbaly through
some kind of symbol table lookup) such that every :abc is the same
symbol.

I don't think anything else works this way either, symbols have a
particular use case that is different to strings, and Ruby can play
with both.

Could you make floats work the same way as symbols? =A0Probably. =A0Is it
worth it? =A0Under what use case is it important that all 12.0s be the
exact same object?

I don't think it's worthwhile because at any point in time there are
not many float instances with the same value other than in artificial
test cases. The price to pay (memory, see above) is just too high.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
R

Robert Klemme

2009/12/22 Florian Gilcher said:
Pretty easy: false and true.

irb(main):001:0> true.object_id
=> 2
irb(main):002:0> false.object_id
=> 0

You need to know but there is a way that works without oracle turing machine:

irb(main):005:0> 10.times {|i| printf "%4d %p\n", i,
ObjectSpace._id2ref(i) rescue nil}
0 false
1 0
2 true
3 1
4 nil
5 2
7 3
9 4
=> 10

:)

Kind regards

robert
 
P

Paul Smith

Pretty easy: false and true.

irb(main):001:0> true.object_id
=> 2
irb(main):002:0> false.object_id
=> 0

Hah, of course. Obvious in retrospect, but I was so surprised to see
that nil wasn't 0 :)
 
R

Rajinder Yadav

Paul said:
Fixnums are immediate in MRI (Matz's Ruby Interpreter) by using odd
numbered object_ids. The Fixnum 0 is represented by the object_id 1.
1 had id 3, 2 has id 5, 3 has id 7.

nil has the object_id 4.

I have no idea what, if anything, has the object_ids 0, and 2.

Bignums (integers past a certain size) don't fit in this scheme (too
big to store in the object_id) so are constructed separately. AFAIK
no other object type uses the object_id trick to made Fixnum's
immediate. This may be different in other Ruby implementations. It's
entirely feasible that a Ruby implementation exists which does not
make Fixnum's immediate.

I think that if you understand how Fixnum's (and nil) are made
immediate, you realise that it's hard to coerce other object types,
like Floats, into this scheme.

Thanks Paul for the explanation, it's immediately obvious (now) how
immediate ids are assigned (no pun intended). I got a deeper
appreciation & understanding for Ruby.
 
R

Rajinder Yadav

Robert said:
You need to know but there is a way that works without oracle turing machine:

irb(main):005:0> 10.times {|i| printf "%4d %p\n", i,
ObjectSpace._id2ref(i) rescue nil}
0 false
1 0
2 true
3 1
4 nil
5 2
7 3
9 4
=> 10

:)

Kind regards

robert

Robert thanks for the code snippet, that is so cool =) ... more stuff to
add to my notes!

--
Kind Regards,
Rajinder Yadav

http://DevMentor.org

Do Good! - Share Freely
 
F

Florian Gilcher

2009/12/22 Florian Gilcher said:
=20
On Dec 22, 2009, at 11:03 AM, Paul Smith wrote:
=20
=20
You need to know but there is a way that works without oracle turing = machine:
=20
irb(main):005:0> 10.times {|i| printf "%4d %p\n", i,
ObjectSpace._id2ref(i) rescue nil}
0 false
1 0
2 true
3 1
4 nil
5 2
7 3
9 4
=3D> 10
=20
:)
=20
Kind regards
=20
robert

I didn't use oracle turing machine, I only used irb to validate my =
pre-existing knowledge.

But thanks for the trick :).

Regards,
Florian=
 
R

Robert Klemme

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

building ruby from source 13
subscribing to ruby-core 2
haml 8
creating a openstruct from xml 4
PDF Viewer 3
downloading a file 11
Happy Holidays 4
building from source 2

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,144
Latest member
KetoBaseReviews
Top