Negative numbers and binary formats

Im trying to take a negative integer value, convert it to its binary
equivalent, and save its hex value

-7 -> 1111 1001 -> F9

I was hoping to use sprintf, but:

irb(main):017:0> b = sprintf("%4b" , a)
=> "..1001"
irb(main):018:0>

The .. that appear break any further processing. So my questions are:

Why the dots, and what are they?
How do I do what Im trying to do - given my -7 in the example may be a
1 byte, 2 byte or 4 byte value. ( Im sure its some magic with
pack....)

Thanks

Paul

Paul wrote:

Moin!

Im trying to take a negative integer value, convert it to its binary
equivalent, and save its hex value

-7 -> 1111 1001 -> F9

Does this help?

irb(main):032:0> [-7].pack("c").unpack("H*").first
=> "f9"

Thanks
Paul

Regards,
Florian Gross

you have a couple of options:

the method of Fixnum returns the bit:

   harp:~ > cat a.rb
   class Fixnum
     def to_bin
       packed = [self].pack 'N'
       n_bytes = packed.size
       n_bits = n_bytes * 8
       s = ''
       n_bits.times{|bit| s << self[n_bits - bit].to_s}
       s
     end
   end

   p 42.to_bin
   p -7.to_bin

   harp:~ > ruby a.rb
   "00000000000000000000000000010101"
   "11111111111111111111111111111100"

but perhaps only printf will suffice?

   irb(main):003:0> printf "%32.32b", -7
   11111111111111111111111111111001=> nil

   irb(main):009:0> printf "%4.4o", -7
   7771=> nil

but i'm not exactly sure where you are headed with this.

the '...' above is just showing you the extension of the sign bit.

-a

···

On Wed, 22 Sep 2004, Paul wrote:

Im trying to take a negative integer value, convert it to its binary
equivalent, and save its hex value

-7 -> 1111 1001 -> F9

I was hoping to use sprintf, but:

irb(main):017:0> b = sprintf("%4b" , a)
=> "..1001"
irb(main):018:0>

The .. that appear break any further processing. So my questions are:

Why the dots, and what are they?
How do I do what Im trying to do - given my -7 in the example may be a
1 byte, 2 byte or 4 byte value. ( Im sure its some magic with
pack....)

Thanks

Paul

--

EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov
PHONE :: 303.497.6469
A flower falls, even though we love it;
and a weed grows, even though we do not love it. --Dogen

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

Im trying to take a negative integer value, convert it to its binary
equivalent, and save its hex value

    So, are you wanting it in binary or in hex?

    Assuming (from your context) that you're wanting it in hexadecimal
(base 16) instead of binary (base 2) you could write:

    (a & 0xff).to_s(16)

for one byte values,

    (a & 0xffff).to_s(16)

for two byte values, etc.

If you are wanting it in binary you would instead write:

    (a & 0xff).to_s(2)

How do I do what Im trying to do - given my -7 in the example may be a
1 byte, 2 byte or 4 byte value.

If you don't know at code-time how large the value will be, but can
determine it at run-time, you could write:

     (a & (((1 << (8*n)) - 1)).to_s(16)

where n is the number of bytes in a and the expression involving a makes
a mask if the proper size. Alternatively, you could mess with the
result instead, by writing:

     ("0"*8 + (a & 0xffffffff).to_s(16))[-n*2..-1]

which pads the result with zeros and then takes the least significant 2n
hexits (i.e, the bottom n bytes).

-- Markus

···

On Wed, 2004-09-22 at 11:14, Paul wrote:

Im trying to take a negative integer value, convert it to its binary
equivalent, and save its hex value

-7 -> 1111 1001 -> F9

I was hoping to use sprintf, but:

irb(main):017:0> b = sprintf("%4b" , a)
=> "..1001"
irb(main):018:0>

The .. that appear break any further processing. So my questions are:

Why the dots, and what are they?

How do I do what Im trying to do - given my -7 in the example may be a
1 byte, 2 byte or 4 byte value. ( Im sure its some magic with
pack....)

well, if all you need is the hex part, here you go:

class Integer
   def internal_hex
     # choose a packing strategy
     case self
     when (-128..127) # char
       [self].pack('c').unpack('C').first.to_s 16
     when (-32768..32767) # short
       [self].pack('s').unpack('S').first.to_s 16
     when (-2147483648..2147483647) # long
       [self].pack('l').unpack('L').first.to_s 16
     else
       "too big!" # :slight_smile:
     end
   end
end

-7.internal_hex #=>"f9"

the hex string will be in big-endian (network) byte-order; that's the way to_s(16) does it.

cheers
Mark

···

On Sep 22, 2004, at 11:14 AM, Paul wrote:

Thanks

Paul

<Ara.T.Howard@noaa.gov> schrieb im Newsbeitrag
news:Pine.LNX.4.60.0409221228140.2168@harp.ngdc.noaa.gov...

but perhaps only printf will suffice?

   irb(main):003:0> printf "%32.32b", -7
   11111111111111111111111111111001=> nil

Hm...

10:25:20 [source]: irb
irb(main):001:0> printf "%32.32b", -7
00000000000000000000000000001001=> nil
irb(main):002:0> RUBY_VERSION
=> "1.8.1"

    robert

"Florian Gross" <flgr@ccan.de> schrieb im Newsbeitrag
news:2rduavF18hbhuU1@uni-berlin.de...

Paul wrote:

Moin!

> Im trying to take a negative integer value, convert it to its binary
> equivalent, and save its hex value
>
> -7 -> 1111 1001 -> F9

Does this help?

irb(main):032:0> [-7].pack("c").unpack("H*").first
=> "f9"

That's nice although it is somewhat limited regarding the size of values:

[-7000].pack("c").unpack("H*").first

=> "a8"

After a bit experimenting I came up with this:

[-7].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')

=> "f9"

[-7000000].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')

=> "f953040"

Florian, what do you think?

Kind regards

    robert

Robert Klemme wrote:

After a bit experimenting I came up with this:

[-7].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')

=> "f9"

[-7000000].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')

=> "f953040"

Florian, what do you think?

Very nice, thank you. I wasn't aware of the range limit at first. Only thing I would change is using .first instead of .shift. (For clarity)

Kind regards
    robert

More regards,
Florian Gross

"Florian Gross" <flgr@ccan.de> schrieb im Newsbeitrag
news:2rfrmgF18j1b3U1@uni-berlin.de...

Robert Klemme wrote:

> After a bit experimenting I came up with this:
>>>[-7].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')
>
> => "f9"
>
>>>[-7000000].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')
>
> => "f953040"
>
> Florian, what do you think?

Very nice, thank you. I wasn't aware of the range limit at first. Only
thing I would change is using .first instead of .shift. (For clarity)

:-)) I deliberately choose #shift in order to make the array a bit
smaller and remove all unnecessary references to the string - kind of GC
paranoid. :slight_smile:

Regards

    robert

> >>>[-7000000].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/, '')

> Very nice, thank you. I wasn't aware of the range limit at first. Only
> thing I would change is using .first instead of .shift. (For clarity)

:-)) I deliberately choose #shift in order to make the array a bit
smaller and remove all unnecessary references to the string - kind of GC
paranoid. :slight_smile:

But:
     1. the array can't be referenced after the first/shift returns
        (since it was an anonymous link in a message chain), so the
        whole array is subject to GC from that point
     2. shift can be significantly slower than first
     3. how do you know that shift isn't doing something like:

def Array.shift
    result = @hypothetical_primitive_array[0]
    @hypothetical_primitive_array = @hypothetical_primitive_array[1..-1]
    result
    end

        ...in which case you'd still have the (scavengable) copy around
        just as if you'd done it yourself?
        
It only pays to be paranoid if you can trust yourself more than you can
trust "them".

-- Markus

"Markus" <markus@reality.com> schrieb im Newsbeitrag
news:1095953157.5019.15.camel@lapdog.reality.com...

> > >>>[-7000000].pack("i").unpack("h*").shift.reverse.gsub(/^f+(?=f)/,

'')

> > Very nice, thank you. I wasn't aware of the range limit at first.

Only

> > thing I would change is using .first instead of .shift. (For

clarity)

>
> :-)) I deliberately choose #shift in order to make the array a bit
> smaller and remove all unnecessary references to the string - kind of

GC

> paranoid. :slight_smile:

But:
     1. the array can't be referenced after the first/shift returns
        (since it was an anonymous link in a message chain), so the
        whole array is subject to GC from that point
     2. shift can be significantly slower than first
     3. how do you know that shift isn't doing something like:

def Array.shift
    result = @hypothetical_primitive_array[0]
    @hypothetical_primitive_array = @hypothetical_primitive_array[1..-1]
    result
    end

        ...in which case you'd still have the (scavengable) copy around
        just as if you'd done it yourself?

It only pays to be paranoid if you can trust yourself more than you can
trust "them".

LOL

Lession taken. Thanks! Of course you're right. Now I just need to find
out who is "me" and "them"...

    robert