Skip to content

Update count_number_of_one_bits.py #7589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 24, 2022
79 changes: 68 additions & 11 deletions bit_manipulation/count_number_of_one_bits.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,91 @@
def get_set_bits_count(number: int) -> int:
from timeit import timeit


def get_set_bits_count_using_brian_kernighans_algorithm(number: int) -> int:
"""
Count the number of set bits in a 32 bit integer
>>> get_set_bits_count(25)
>>> get_set_bits_count_using_brian_kernighans_algorithm(25)
3
>>> get_set_bits_count(37)
>>> get_set_bits_count_using_brian_kernighans_algorithm(37)
3
>>> get_set_bits_count(21)
>>> get_set_bits_count_using_brian_kernighans_algorithm(21)
3
>>> get_set_bits_count(58)
>>> get_set_bits_count_using_brian_kernighans_algorithm(58)
4
>>> get_set_bits_count(0)
>>> get_set_bits_count_using_brian_kernighans_algorithm(0)
0
>>> get_set_bits_count(256)
>>> get_set_bits_count_using_brian_kernighans_algorithm(256)
1
>>> get_set_bits_count(-1)
>>> get_set_bits_count_using_brian_kernighans_algorithm(-1)
Traceback (most recent call last):
...
ValueError: the value of input must be positive
ValueError: the value of input must not be negative
"""
if number < 0:
raise ValueError("the value of input must be positive")
raise ValueError("the value of input must not be negative")
result = 0
while number:
number &= number - 1
result += 1
return result


def get_set_bits_count_using_modulo_operator(number: int) -> int:
"""
Count the number of set bits in a 32 bit integer
>>> get_set_bits_count_using_modulo_operator(25)
3
>>> get_set_bits_count_using_modulo_operator(37)
3
>>> get_set_bits_count_using_modulo_operator(21)
3
>>> get_set_bits_count_using_modulo_operator(58)
4
>>> get_set_bits_count_using_modulo_operator(0)
0
>>> get_set_bits_count_using_modulo_operator(256)
1
>>> get_set_bits_count_using_modulo_operator(-1)
Traceback (most recent call last):
...
ValueError: the value of input must not be negative
"""
if number < 0:
raise ValueError("the value of input must not be negative")
result = 0
while number:
if number % 2 == 1:
result += 1
number = number >> 1
number >>= 1
return result


def benchmark() -> None:
"""
Benchmark code for comparing 2 functions, with different length int values.
Brian Kernighan's algorithm is consistently faster than using modulo_operator.
"""

def do_benchmark(number: int) -> None:
setup = "import __main__ as z"
print(f"Benchmark when {number = }:")
print(f"{get_set_bits_count_using_modulo_operator(number) = }")
timing = timeit("z.get_set_bits_count_using_modulo_operator(25)", setup=setup)
print(f"timeit() runs in {timing} seconds")
print(f"{get_set_bits_count_using_brian_kernighans_algorithm(number) = }")
timing = timeit(
"z.get_set_bits_count_using_brian_kernighans_algorithm(25)",
setup=setup,
)
print(f"timeit() runs in {timing} seconds")

for number in (25, 37, 58, 0):
do_benchmark(number)
print()


if __name__ == "__main__":
import doctest

doctest.testmod()
benchmark()