Forum: Ruby Ruby's Bignum

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
A24e072d6092870feff0d5016ff2cdd0?d=identicon&s=25 Aaron Patterson (Guest)
on 2006-06-04 08:36
(Received via mailing list)
Hi everyone.  I'm porting some C code to pure ruby, and I would like to
keep Ruby from turning my numbers in to Bignums.  Is that possible?

For example, in C:

  printf("number: %d\n", 0xd76aa478);

Prints "number: -680876936"

In ruby:

irb(main):001:0> puts 0xd76aa478
3614090360
=> nil

Is it possible to get ruby to behave the same way as C?  This seems like
something easy to do, I'm just having a hard time figuring it out.
Thank you!

--Aaron
E51d56251ec4affafe85ee9367228965?d=identicon&s=25 Park Heesob (Guest)
on 2006-06-04 09:24
(Received via mailing list)
Hi,

>
>Is it possible to get ruby to behave the same way as C?  This seems like
>something easy to do, I'm just having a hard time figuring it out.
>Thank you!
>
Try this:

irb(main):001:0> puts [0xd76aa478].pack('L').unpack('l').first
-680876936
=> nil


Regards,

Park Heesob
B5e329ffa0cc78efbfc7ae2d084c149f?d=identicon&s=25 David Balmain (Guest)
on 2006-06-04 09:28
(Received via mailing list)
On 6/4/06, Aaron Patterson <aaron_patterson@speakeasy.net> wrote:
>
> irb(main):001:0> puts 0xd76aa478
> 3614090360
> => nil
>
> Is it possible to get ruby to behave the same way as C?  This seems like
> something easy to do, I'm just having a hard time figuring it out.
> Thank you!

Hi Aaron,

Short answer, no. In Ruby, as you know, everything is an object and in
the C code implementing ruby, this is represented by pointers to these
objects. These pointers have a type of VALUE which is basically a
32-bit integer. But it would be pretty inefficient to store integers
as memory-allocated objects so instead it stores them in the same
32-bit integer. (This is true for FixInt, BigNum is an object ref). So
how does the interpreter know the difference between an object
reference and a FixInt? It relies on the fact that all memory pointers
are are on 4 or 8-byte boundaries so that leaves at least the last 2
bits free. These last two bits are used to specify whether VALUE is an
integer, a refence or possibly a symbol, true or false value or nil.
This means that there are only 30 bits left to specify the value of
FixInt. So the maximum value you can store in a FixInt is 0x3FFFFFFF
and the minimum is -0x40000000.

irb(main):007:0> 0x40000000.class
=> Bignum
irb(main):008:0> 0x3fffffff.class
=> Fixnum
irb(main):009:0> -0x40000000.class
=> Fixnum
irb(main):010:0> -0x40000001.class
=> Bignum

Hope that makes sense.

Cheers,
Dave
B5e329ffa0cc78efbfc7ae2d084c149f?d=identicon&s=25 David Balmain (Guest)
on 2006-06-04 09:40
(Received via mailing list)
On 6/4/06, David Balmain <dbalmain.ml@gmail.com> wrote:
> > In ruby:
>
> integer, a refence or possibly a symbol, true or false value or nil.
> irb(main):010:0> -0x40000001.class
> => Bignum
>
> Hope that makes sense.
>
> Cheers,
> Dave

Sorry, this answer should have been under "and I would like to keep
Ruby from turning my numbers in to Bignums.  Is that possible?"

To cast an Integer to a 32-bit signed integer you can use pack/unpack
like Park said, or you could do it like this;

def to_32_bit_signed(val)
    val |= -0x100000000 if (val & 0x80000000) > 0
    val
end
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-06-04 11:34
(Received via mailing list)
2006/6/4, David Balmain <dbalmain.ml@gmail.com>:
> On 6/4/06, David Balmain <dbalmain.ml@gmail.com> wrote:
> To cast an Integer to a 32-bit signed integer you can use pack/unpack
> like Park said, or you could do it like this;
>
> def to_32_bit_signed(val)
>     val |= -0x100000000 if (val & 0x80000000) > 0
>     val
> end

And if you need this in multiple places of the program then it's
probably worth while to create a new subclass of Integer that
restricts itself to 32 bit calculations

Int32 < Integer
  def initialize(x)
    @val = to_32(x)
  end
  def to_int ...
  def coerce(a,b) ...
  def hash() ...
  def eql?(x)
  def ==(x) ...
  def +(x) ...
  def -(x) ...
private
  def to_32(x) ...

end

It's a nice excercise to get used to operators and numercial coercion.
:-)

Maybe we can even generalize that and put it into the standard lib -
something like a restricted integer that calculates with a max number
of bits.

Kind regards

robert
56f2ce19706d05d18b5b66483aa13f98?d=identicon&s=25 Lloyd Zusman (Guest)
on 2006-06-04 16:19
(Received via mailing list)
"Robert Klemme" <shortcutter@googlemail.com> writes:

> And if you need this in multiple places of the program then it's
>   def eql?(x)
> Maybe we can even generalize that and put it into the standard lib -
> something like a restricted integer that calculates with a max number
> of bits.

This is indeed a good Ruby exercise, but if it ever ends up in the
standard library, I would then vote for it to be re-implemented in C, as
the Ruby version would be hugely less efficient than the native
32-bit-integer operations that are already available in C.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2006-06-04 18:57
(Received via mailing list)
2006/6/4, Lloyd Zusman <ljz@asfast.com>:

> > And if you need this in multiple places of the program then it's
> > probably worth while to create a new subclass of Integer that
> > restricts itself to 32 bit calculations

> > It's a nice excercise to get used to operators and numercial coercion. :-)
> >
> > Maybe we can even generalize that and put it into the standard lib -
> > something like a restricted integer that calculates with a max number
> > of bits.
>
> This is indeed a good Ruby exercise, but if it ever ends up in the
> standard library, I would then vote for it to be re-implemented in C, as
> the Ruby version would be hugely less efficient than the native
> 32-bit-integer operations that are already available in C.

Completely agree!

robert
A24e072d6092870feff0d5016ff2cdd0?d=identicon&s=25 Aaron Patterson (Guest)
on 2006-06-04 19:58
(Received via mailing list)
On Sun, Jun 04, 2006 at 04:23:38PM +0900, Park Heesob wrote:
> Try this:
>
> irb(main):001:0> puts [0xd76aa478].pack('L').unpack('l').first
> -680876936
> => nil
>

Thanks Park!  Thats exactly what I was looking for.

--Aaron
47b1910084592eb77a032bc7d8d1a84e?d=identicon&s=25 Joel VanderWerf (Guest)
on 2006-06-04 20:13
(Received via mailing list)
Aaron Patterson wrote:
> Hi everyone.  I'm porting some C code to pure ruby, and I would like to
> keep Ruby from turning my numbers in to Bignums.  Is that possible?
>
> For example, in C:
>
>   printf("number: %d\n", 0xd76aa478);
>
> Prints "number: -680876936"

It's just another variation on pack/unpack, but with bit-struct (from
RAA):

require 'bit-struct'

class C < BitStruct
  signed    :foo,   32
end

c = C.new
c.foo = 0xd76aa478

printf("number: %d\n", c.foo)
# ==> number: -680876936
A24e072d6092870feff0d5016ff2cdd0?d=identicon&s=25 Aaron Patterson (Guest)
on 2006-06-04 20:30
(Received via mailing list)
On Sun, Jun 04, 2006 at 06:32:54PM +0900, Robert Klemme wrote:
[snip]
>
> It's a nice excercise to get used to operators and numercial coercion. :-)
>
> Maybe we can even generalize that and put it into the standard lib -
> something like a restricted integer that calculates with a max number
> of bits.

I was hoping this would be in the standard lib since I have to do it a
lot!  I will be filling out that class so that I won't have to type as
much though.  :-)

--Aaron
This topic is locked and can not be replied to.