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
Hi,
From: Aaron Patterson <aaron_patterson@speakeasy.net>
Reply-To: ruby-talk@ruby-lang.org
To: ruby-talk@ruby-lang.org (ruby-talk ML)
Subject: Ruby's Bignum
Date: Sun, 4 Jun 2006 15:34:59 +0900
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!
Try this:
irb(main):001:0> puts [0xd76aa478].pack('L').unpack('l').first
-680876936
=> nil
Regards,
Park Heesob
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!
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
···
On 6/4/06, Aaron Patterson <aaron_patterson@speakeasy.net> wrote:
--Aaron
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
···
--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407
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
···
On 6/4/06, David Balmain <dbalmain.ml@gmail.com> wrote:
On 6/4/06, Aaron Patterson <aaron_patterson@speakeasy.net> 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"
>
> 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!
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
Thanks Park! Thats exactly what I was looking for.
--Aaron
···
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
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
···
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
--
Have a look: http://www.flickr.com/photos/fussel-foto/
"Robert Klemme" <shortcutter@googlemail.com> writes:
···
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.
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.
--
Lloyd Zusman
ljz@asfast.com
God bless you.
[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
···
On Sun, Jun 04, 2006 at 06:32:54PM +0900, Robert Klemme wrote: