How convert an integer to a bit array

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Curt

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Does this help?

>> ("%b" % 5).split("").map { |n| n.to_i }
=> [1, 0, 1]

James Edward Gray II

···

On Nov 22, 2005, at 4:23 PM, Curt Hibbs wrote:

Curt Hibbs wrote:

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Curt

s = ""
s[0] = 7
s.unpack("B*")[0].split("").map{|bit|bit.to_i}
=> [0, 0, 0, 0, 0, 1, 1, 1]

It should be easier than that, though.

···

--
      vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Curt Hibbs wrote:

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Curt

irb(main):082:0> x = 7.to_s(2).split(//).map! {|bit| bit.to_i}
=> [1, 1, 1]
irb(main):083:0> x.unshift(0) until x.length == 8

if your number always fit into 8 bit
otherwise this doesn't work

Regards, Daniel

This way is about 4 times faster than James' version:

class Integer
  def to_ba(size=8)
    a=
    (size-1).downto(0) do |i|
      a<<self[i]
    end
    a
  end
end

p 0.to_ba
p 1.to_ba
p 2.to_ba
p 7.to_ba
__END__

Result:

[0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 1, 1, 1]

Ryan

···

On 11/22/05, Curt Hibbs <curt.hibbs@gmail.com> wrote:

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Another thought: Ruby's Integers are already pretty close to a bit Array. If you only need to index the bits, maybe it's best not to convert at all...

James Edward Gray II

···

On Nov 22, 2005, at 4:23 PM, Curt Hibbs wrote:

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Last idea:

>> bits = Array.new(8) { |i| 7[i] }.reverse!
=> [0, 0, 0, 0, 0, 1, 1, 1]

I promise to stop spamming this thread now. :wink:

James Edward Gray II

···

On Nov 22, 2005, at 4:23 PM, Curt Hibbs wrote:

An alternative to ('%b' % n) is n.to_s(2)

marcel

···

On Wed, Nov 23, 2005 at 07:31:02AM +0900, James Edward Gray II wrote:

On Nov 22, 2005, at 4:23 PM, Curt Hibbs wrote:

>Does anyone have a clever way to convert an integer to an array of bit
>values?
>
>For example (using 8 bit integers):
>
>0 => [0, 0, 0, 0, 0, 0, 0, 0]
>1 => [0, 0, 0, 0, 0, 0, 0, 1]
>2 => [0, 0, 0, 0, 0, 0, 1, 0]
>7 => [0, 0, 0, 0, 0, 1, 1, 1]
>etc.
>
>I was looking at Array#pack and Array#unpack to do this, but
>haven't figured
>it out yet. It just seems like there ought to be a simple way to do
>this.
>
>Anybody got a clever idea?

Does this help?

>> ("%b" % 5).split("").map { |n| n.to_i }
=> [1, 0, 1]

--
Marcel Molina Jr. <marcel@vernix.org>

s = ""
s[0] = 7
s.unpack("B*")[0].split("").map{|bit|bit.to_i}
=> [0, 0, 0, 0, 0, 1, 1, 1]

It should be easier than that, though.

How about:

num = 50

num.to_s(2).split("").map{ |bit| bit.to_i}

There's problably some trickery with String.each_with_index you can do to make the map a little simpler.

You could do this:

x.unshift(0) until (x.size % 8).zero?

marcel

···

On Wed, Nov 23, 2005 at 07:37:25AM +0900, Daniel Sch?le wrote:

Curt Hibbs wrote:
>Does anyone have a clever way to convert an integer to an array of bit
>values?
>
>For example (using 8 bit integers):
>
>0 => [0, 0, 0, 0, 0, 0, 0, 0]
>1 => [0, 0, 0, 0, 0, 0, 0, 1]
>2 => [0, 0, 0, 0, 0, 0, 1, 0]
>7 => [0, 0, 0, 0, 0, 1, 1, 1]
>etc.
>
>I was looking at Array#pack and Array#unpack to do this, but haven't
>figured
>it out yet. It just seems like there ought to be a simple way to do this.
>
>Anybody got a clever idea?
>
>Curt

irb(main):082:0> x = 7.to_s(2).split(//).map! {|bit| bit.to_i}
=> [1, 1, 1]
irb(main):083:0> x.unshift(0) until x.length == 8

if your number always fit into 8 bit
otherwise this doesn't work

--
Marcel Molina Jr. <marcel@vernix.org>

For those curious:

···

On 11/22/05, Ryan Leavengood <leavengood@gmail.com> wrote:

This way is about 4 times faster than James' version:

----------------------------------------------------------------------

                    QuickBench Session Started |
                        100000 Iterations |

----------------------------------------------------------------------
                               user system total real
1. 244.to_ba 1.171000 0.000000 1.171000 ( 1.172000)
2. ("%b" % 244).split(... 4.735000 0.000000 4.735000 ( 4.750000)
3. s.unpack("B*")[0].s... 4.156000 0.000000 4.156000 ( 4.156000)
4. 244.to_s(2).split("... 4.422000 0.000000 4.422000 ( 4.437000)
----------------------------------------------------------------------

                    Fastest was <1. 244.to_ba> |

----------------------------------------------------------------------

QuickBench is a little script I wrote, which I may or may not release
into the wild.

The code will follow my name (note how I use the DATA section for the
things to benchmark):

Ryan "Mr. Benchmark" Leavengood

class Integer
  def to_ba(size=8)
    a=
    (size-1).downto(0) do |i|
      a<<self[i]
    end
    a
  end
end

require 'quickbench'
s=" "
s[0]=244
QuickBench.go(100000, 22) {}
__END__
244.to_ba
("%b" % 244).split("").map { |n| n.to_i }
s.unpack("B*")[0].split("").map{|bit|bit.to_i}
244.to_s(2).split("").map{ |bit| bit.to_i}

You guys are awesome... so many good ideas here!

Thanks,
Curt

And the winner by a nose is.................................
...............................
...............................
James!!!

···

On 11/22/05, James Edward Gray II <james@grayproductions.net> wrote:

>> bits = Array.new(8) { |i| 7[i] }.reverse!
=> [0, 0, 0, 0, 0, 1, 1, 1]

----------------------------------------------------------------------

                    QuickBench Session Started |
                        300000 Iterations |

----------------------------------------------------------------------
                               user system total real
1. 244.to_ba 3.296000 0.015000 3.311000 ( 3.313000)
2. Array.new(8) { |i| ... 2.782000 0.000000 2.782000 ( 2.781000)
----------------------------------------------------------------------

             Fastest was <2. Array.new(8) { |i| ...> |

----------------------------------------------------------------------

I'm glad you posted this because it is elegant and fast. OK, now I'll
stop spamming this thread with benchmark results :slight_smile:

Regards,
Ryan

Marcel Molina Jr. wrote:

···

On Wed, Nov 23, 2005 at 07:37:25AM +0900, Daniel Sch?le wrote:

Curt Hibbs wrote:

Does anyone have a clever way to convert an integer to an array of bit
values?

For example (using 8 bit integers):

0 => [0, 0, 0, 0, 0, 0, 0, 0]
1 => [0, 0, 0, 0, 0, 0, 0, 1]
2 => [0, 0, 0, 0, 0, 0, 1, 0]
7 => [0, 0, 0, 0, 0, 1, 1, 1]
etc.

I was looking at Array#pack and Array#unpack to do this, but haven't figured
it out yet. It just seems like there ought to be a simple way to do this.

Anybody got a clever idea?

Curt

irb(main):082:0> x = 7.to_s(2).split(//).map! {|bit| bit.to_i}
=> [1, 1, 1]
irb(main):083:0> x.unshift(0) until x.length == 8

if your number always fit into 8 bit
otherwise this doesn't work

You could do this:

x.unshift(0) until (x.size % 8).zero?

marcel

Nah, that's too much work.

x = ("%08d" % 7.to_s(2)).split('').map{ |e| e.to_i }

Replace 8 with the integer size and 7 with whatever number you're converting.

Regards,

Dan

Cool! Thanks for doing the benchmark.

Curt

···

On 11/23/05, Ryan Leavengood <leavengood@gmail.com> wrote:

On 11/22/05, James Edward Gray II <james@grayproductions.net> wrote:
>
> >> bits = Array.new(8) { |i| 7[i] }.reverse!
> => [0, 0, 0, 0, 0, 1, 1, 1]

And the winner by a nose is.................................
...............................
...............................
James!!!

----------------------------------------------------------------------
> QuickBench Session Started |
> 300000 Iterations |
----------------------------------------------------------------------
                               user system total real
1. 244.to_ba 3.296000 0.015000 3.311000 ( 3.313000)
2. Array.new(8) { |i| ... 2.782000 0.000000 2.782000 ( 2.781000)
----------------------------------------------------------------------
> Fastest was <2. Array.new(8) { |i| ...> |
----------------------------------------------------------------------

I'm glad you posted this because it is elegant and fast. OK, now I'll
stop spamming this thread with benchmark results :slight_smile:

>
> >
> > >> bits = Array.new(8) { |i| 7[i] }.reverse!
> > => [0, 0, 0, 0, 0, 1, 1, 1]
>
> And the winner by a nose is

...

> James!!!
>

def to_ba(num, size=8)
  (-size+1..0).inject({}) {|x,i| x << num[-i]}
end

to_ba(15)
=> [0,0,0,0,1,1,1,1]

It may be a tad faster, the bigger the array, due to the lack of
reverse. Can someone bench it? I don't have require 'quickbench'

Or perhaps, modifying James':

def to_ba(num, size=8)
  Array.new(size) {|i| num[-i+size-1]}
end

Ed

···

On 11/23/05, Curt Hibbs <curt.hibbs@gmail.com> wrote:

On 11/23/05, Ryan Leavengood <leavengood@gmail.com> wrote:
> On 11/22/05, James Edward Gray II <james@grayproductions.net> wrote: