Skip to content

Instantly share code, notes, and snippets.

@mark
Created October 10, 2013 03:42
Show Gist options
  • Save mark/6912695 to your computer and use it in GitHub Desktop.
Save mark/6912695 to your computer and use it in GitHub Desktop.
Different ways of counting the # of bits in a number
require 'benchmark'
class Fixnum
def bitcount1
c = 0; n = self
while n > 0
c += n&1
n >>= 1
end
c
end
def bitcount2
c = 0; n = self
while n > 0
c += n&1
c += n&2 > 0 ? 1 : 0
c += n&4 > 0 ? 1 : 0
c += n&8 > 0 ? 1 : 0
n >>= 4
end
c
end
BITCOUNT_ARRAY = [0,1,1,2,1,2,2,3]
def bitcount3
c = 0; n = self
while n > 0
c += BITCOUNT_ARRAY[n&7]
n >>= 3
end
c
end
def bitcount4
c = 0; n = self
while n > 0
c += n&1
c += n&2 > 0 ? 1 : 0
c += n&4 > 0 ? 1 : 0
c += n&8 > 0 ? 1 : 0
c += n&16 > 0 ? 1 : 0
c += n&32 > 0 ? 1 : 0
c += n&64 > 0 ? 1 : 0
c += n&128 > 0 ? 1 : 0
n >>= 8
end
c
end
BITCOUNT_ARRAY_2 = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6]
def bitcount5
c = 0; n = self
while n > 0
c += BITCOUNT_ARRAY_2[n&63]
n >>= 6
end
c
end
end
Benchmark.bm do |r|
r.report "bitcount1" do
100_000.times { |i| i.bitcount1 }
end
r.report "bitcount2" do
100_000.times { |i| i.bitcount2 }
end
r.report "bitcount3" do
100_000.times { |i| i.bitcount3 }
end
r.report "bitcount4" do
100_000.times { |i| i.bitcount4 }
end
r.report "bitcount5" do
1_000_000.times { |i| i.bitcount5 }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment