Fixnum's binary representation

Hi, people!

As far as I know, Ruby's Fixnum is 30-bit signed integer.
One bit is used as a flag for whether it's a direct value.
Another bit is used for non-Fixnum direct values.
I wondered how Fixnum#[] works and tested it.

def show_binary(i)
  result = ''
  32.times do |b|
    result = i[b].to_s + result
    if (b % 8 == 7) and (b != 31)
      result = " " + result
    end
  end
  puts result + ": " + i.to_s
end

show_binary(1)
show_binary(-1)
show_binary(2 ** 31 - 1)
show_binary((2 ** 31 - 1) * (-1))

Result:

00000000 00000000 00000000 00000001: 1
11111111 11111111 11111111 11111111: -1
01111111 11111111 11111111 11111111: 2147483647
10000000 00000000 00000000 00000001: -2147483647

This is exactly how 32-bit signed integer's binary representations look
like.
My guess is that Fixnum#[] works as if it's 32-bit signed integer.
It's not showing its real binary representation.
Is my guess true?

My another question is that even if (2 ** 31 - 1) is not a Fixnum, the
above code works for it (Actually Bignum#[]).
If the number is bigger than that, [] doesn't work.
Fixnum#[] and Bignum#[] are cleverly hiding the internal facts and are
made to simulate 32-bit signed integers?

Thanks.
Sam

camsight@gmail.com wrote:

Hi, people!

As far as I know, Ruby's Fixnum is 30-bit signed integer.
One bit is used as a flag for whether it's a direct value.
Another bit is used for non-Fixnum direct values.
I wondered how Fixnum# works and tested it.

look like.
My guess is that Fixnum# works as if it's 32-bit signed integer.
It's not showing its real binary representation.
Is my guess true?

Yes.

My another question is that even if (2 ** 31 - 1) is not a Fixnum, the
above code works for it (Actually Bignum#).
If the number is bigger than that, doesn't work.

For which numbers do you have problems? I don't see any so far

100.times {|sh| raise unless sh==0||(1 << sh)[0] == 0}

=> 100

(1<<100).class

=> Bignum

Fixnum# and Bignum# are cleverly hiding the internal facts and are
made to simulate 32-bit signed integers?

Yes.

Kind regards

    robert

don't deny yourself the joys of printf :wink:

   harp:~ > cat a.rb
   [ (1), (-1), (2 ** 31 - 1), ((2 ** 31 - 1) * (-1)) ].each{|n| printf "%32.32b\n", n}

   harp:~ > ruby a.rb
   00000000000000000000000000000001
   11111111111111111111111111111111
   01111111111111111111111111111111
   10000000000000000000000000000001

cheers.

-a

···

On Wed, 4 May 2005 camsight@gmail.com wrote:

Hi, people!

As far as I know, Ruby's Fixnum is 30-bit signed integer.
One bit is used as a flag for whether it's a direct value.
Another bit is used for non-Fixnum direct values.
I wondered how Fixnum# works and tested it.

def show_binary(i)
  result = ''
  32.times do |b|
    result = i[b].to_s + result
    if (b % 8 == 7) and (b != 31)
      result = " " + result
    end
  end
  puts result + ": " + i.to_s
end

show_binary(1)
show_binary(-1)
show_binary(2 ** 31 - 1)
show_binary((2 ** 31 - 1) * (-1))

Result:

00000000 00000000 00000000 00000001: 1
11111111 11111111 11111111 11111111: -1
01111111 11111111 11111111 11111111: 2147483647
10000000 00000000 00000000 00000001: -2147483647

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
renunciation is not getting rid of the things of this world, but accepting
that they pass away. --aitken roshi

===============================================================================

$ ruby
puts (-10..10).map { |i| "#{i}: #{i.object_id}" }.join("\n")
-5: -9
-4: -7
-3: -5
-2: -3
-1: -1
0: 1
1: 3
2: 5
3: 7
4: 9
5: 11

A Fixnum's object_id is 2N+1 its value, so if you want a Fixnum's binary representation, use its object_id. (So long as the object_id is a Fixnum.)

#define FIXNUM_FLAG 0x01
#define INT2FIX(i) ((VALUE)(((long)(i))<<1 | FIXNUM_FLAG))

Also, a Fixnum always has an odd object_id, while any other VALUE has an even object_id.

···

On 04 May 2005, at 09:04, camsight@gmail.com wrote:

Hi, people!

As far as I know, Ruby's Fixnum is 30-bit signed integer.
One bit is used as a flag for whether it's a direct value.
Another bit is used for non-Fixnum direct values.

My guess is that Fixnum# works as if it's 32-bit signed integer.
It's not showing its real binary representation.
Is my guess true?

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

Thanks, Robert!

For which numbers do you have problems? I don't see any so far

I mean...
If Bignum# is made to simulate 32-bit signed integers, it can't show
numbers with more than 32-bit representation.
Well, positive numbers will be okay.
But what about negative numbers?
When can I expect the sign bit?
I assume that numbers beyond 32-bit are not suitable for Bignum#.
Do you agree?

Thanks again.

Sam

Wow, that's great.
I have to learn more...:slight_smile:

Thanks.
Sam

Hmmm... this is very interesting.
Thanks.

Sam

IIUC, it's not precisely a "sign bit"; it's more like an entire
bit-flip. -1 is zero, bit-flipped. So if you are trying to use
Integer# to get determine the sign of a number, the question is
simply: how high do you want to go? integer[512] will correctly
determine sign for numbers in the range of (-(2**512-1)..2**512) (that
is, a 512 bit integer). There no way (that I can think of) to use
Integer# to return the correct sign on *any* integer usable in Ruby.

hth,
Mark

···

On 5/4/05, camsight@gmail.com <camsight@gmail.com> wrote:

Thanks, Robert!

> For which numbers do you have problems? I don't see any so far

I mean...
If Bignum# is made to simulate 32-bit signed integers, it can't show
numbers with more than 32-bit representation.
Well, positive numbers will be okay.
But what about negative numbers?
When can I expect the sign bit?
I assume that numbers beyond 32-bit are not suitable for Bignum#.
Do you agree?

<camsight@gmail.com> schrieb im Newsbeitrag news:1115223668.955656.66750@o13g2000cwo.googlegroups.com...

Thanks, Robert!

For which numbers do you have problems? I don't see any so far

I mean...
If Bignum# is made to simulate 32-bit signed integers, it can't show
numbers with more than 32-bit representation.
Well, positive numbers will be okay.
But what about negative numbers?
When can I expect the sign bit?

Well, since Bignums can be arbitrary size, you have to decide. The values returned by Fixnum# and Bignum# represent bits of a two complement's arbitrary size binary number. If you view it from this perspective, you'll see that there is no single sign bit. Negative numbers have *all* the higher bits set to 1.

I assume that numbers beyond 32-bit are not suitable for Bignum#.
Do you agree?

Not at all.

n = -(1<<100)

=> -1267650600228229401496703205376

200.times{|i| print i, " ", n[i], "\n"}

0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
....
95 0
96 0
97 0
98 0
99 0
100 1
101 1
102 1
103 1
104 1
....
195 1
196 1
197 1
198 1
199 1
=> 200

As you clearly see, the representation is ok.

Btw, you'll notice the same effect with Fixnum# - because these methods do not represent the actual binary representation in mem but try to represent the general concept of signed binary numbers:

(-1)[100]

=> 1

(-1)[1<<100]

=> 1

Kind regards

    robert

In article <de63abca05050410051035e0c2@mail.gmail.com>,

···

Mark Hubbart <discordantus@gmail.com> wrote:

On 5/4/05, camsight@gmail.com <camsight@gmail.com> wrote:

Thanks, Robert!

> For which numbers do you have problems? I don't see any so far

I mean...
If Bignum# is made to simulate 32-bit signed integers, it can't show
numbers with more than 32-bit representation.
Well, positive numbers will be okay.
But what about negative numbers?
When can I expect the sign bit?
I assume that numbers beyond 32-bit are not suitable for Bignum#.
Do you agree?

IIUC, it's not precisely a "sign bit"; it's more like an entire
bit-flip. -1 is zero, bit-flipped.

It's 2's complement, isn't it?

Phil

Now I understand what you mean.
Thanks a lot!

Sam

Guy's this is very neat and it also brings back some memories.

Some years ago I did quite a lot of programming on CDC 6600 & 7600 at the
ULCC. These machines use exactly the same notation. I remember revelling in
having two zeros because I used to use one to mean null (-1) and the other
zero. Yes programming in FORTRAN and writing COMPASS assembler subroutines
when FORTRAN was stumped. Mmm about 1974-1976 I think.

Kind regards,

Andrew Ballantine

···

----- Original Message -----
From: "Robert Klemme" <bob.news@gmx.net>
Newsgroups: comp.lang.ruby
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Wednesday, May 04, 2005 6:09 PM
Subject: Re: Fixnum's binary representation

<camsight@gmail.com> schrieb im Newsbeitrag
news:1115223668.955656.66750@o13g2000cwo.googlegroups.com...
> Thanks, Robert!
>
>> For which numbers do you have problems? I don't see any so far
>
> I mean...
> If Bignum# is made to simulate 32-bit signed integers, it can't show
> numbers with more than 32-bit representation.
> Well, positive numbers will be okay.
> But what about negative numbers?
> When can I expect the sign bit?

Well, since Bignums can be arbitrary size, you have to decide. The values
returned by Fixnum# and Bignum# represent bits of a two complement's
arbitrary size binary number. If you view it from this perspective,

you'll

see that there is no single sign bit. Negative numbers have *all* the
higher bits set to 1.

> I assume that numbers beyond 32-bit are not suitable for Bignum#.
> Do you agree?

Not at all.

>> n = -(1<<100)
=> -1267650600228229401496703205376
>> 200.times{|i| print i, " ", n[i], "\n"}
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
....
95 0
96 0
97 0
98 0
99 0
100 1
101 1
102 1
103 1
104 1
....
195 1
196 1
197 1
198 1
199 1
=> 200

As you clearly see, the representation is ok.

Btw, you'll notice the same effect with Fixnum# - because these methods

do

not represent the actual binary representation in mem but try to represent
the general concept of signed binary numbers:

>> (-1)[100]
=> 1
>> (-1)[1<<100]
=> 1

Kind regards

    robert

--
No virus found in this incoming message.
Checked by AVG Anti-Virus.
Version: 7.0.308 / Virus Database: 266.11.4 - Release Date: 04/05/2005

(looking it up)

yeah! that's what it is. IANACSM (I am not a CS major) and I still
have terminology to learn. I am woefully ignorant of it, and really
should read some programming theory. When I get the time. :slight_smile:

cheers,
Mark

···

On 5/4/05, Phil Tomson <ptkwt@aracnet.com> wrote:

In article <de63abca05050410051035e0c2@mail.gmail.com>,
Mark Hubbart <discordantus@gmail.com> wrote:
>On 5/4/05, camsight@gmail.com <camsight@gmail.com> wrote:
>> Thanks, Robert!
>>
>> > For which numbers do you have problems? I don't see any so far
>>
>> I mean...
>> If Bignum# is made to simulate 32-bit signed integers, it can't show
>> numbers with more than 32-bit representation.
>> Well, positive numbers will be okay.
>> But what about negative numbers?
>> When can I expect the sign bit?
>> I assume that numbers beyond 32-bit are not suitable for Bignum#.
>> Do you agree?
>
>IIUC, it's not precisely a "sign bit"; it's more like an entire
>bit-flip. -1 is zero, bit-flipped.

It's 2's complement, isn't it?