negative numbers and binary formats

Discussion in 'Ruby' started by Paul, Sep 22, 2004.

  1. Paul

    Paul Guest

    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, Sep 22, 2004
    #1
    1. Advertising

  2. 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
     
    Florian Gross, Sep 22, 2004
    #2
    1. Advertising

  3. Paul

    Guest

    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


    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
    --
    ===============================================================================
    | 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
    ===============================================================================
     
    , Sep 22, 2004
    #3
  4. Paul

    Markus Guest

    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


    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
     
    Markus, Sep 22, 2004
    #4
  5. Paul

    Mark Hubbart Guest

    On Sep 22, 2004, at 11:14 AM, 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!" # :)
    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


    >
    > Thanks
    >
    > Paul
    >
     
    Mark Hubbart, Sep 22, 2004
    #5
  6. <> schrieb im Newsbeitrag
    news:p...

    > 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
     
    Robert Klemme, Sep 23, 2004
    #6
  7. "Florian Gross" <> schrieb im Newsbeitrag
    news:...
    > 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, Sep 23, 2004
    #7
  8. 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, Sep 23, 2004
    #8
  9. "Florian Gross" <> schrieb im Newsbeitrag
    news:...
    > 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. :)

    Regards

    robert
     
    Robert Klemme, Sep 23, 2004
    #9
  10. Paul

    Markus Guest

    > > >>>[-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. :)


    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, Sep 23, 2004
    #10
  11. "Markus" <> schrieb im Newsbeitrag
    news:...
    > > > >>>[-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. :)

    >
    > 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
     
    Robert Klemme, Sep 23, 2004
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. prem_eda
    Replies:
    5
    Views:
    7,870
    Pieter Hulshoff
    Oct 11, 2004
  2. Kevin Spencer
    Replies:
    3
    Views:
    491
    Jerry III
    Aug 22, 2003
  3. Matthew Wilson

    negative numbers and integer division

    Matthew Wilson, Oct 3, 2003, in forum: Python
    Replies:
    7
    Views:
    378
    mensanator
    Oct 3, 2003
  4. Tomi Silander
    Replies:
    3
    Views:
    908
    Grant Edwards
    Apr 6, 2005
  5. Marcelo De Brito

    A Minor Problem With atoi() And Negative Numbers

    Marcelo De Brito, Mar 7, 2010, in forum: C Programming
    Replies:
    12
    Views:
    4,750
    Nick Keighley
    Mar 9, 2010
Loading...

Share This Page