CS 111 f21 — Binary, Hexadecimal, and Binary Search

1 Binary

  • base 10 vs base 2
  • what is a bit?
    • How many bits would be need to represent the numbers 0 to 63?
    • images we've been working with have been 24-bit (8 bits for each color channel)
  • practice conversions:
    • 9 to binary1
    • 00101010 to decimal2

2 Hexadecimal

  • base 16
    • since a single digit in base 16 can be any number between 0 and 15 in base 10, we need new symbols for the numbers beyond 9
    • a, b, c, d, e, f are used for 10, 11, 12, 13, 14, and 15, respectively
  • how many bits per hexadecimal digit?
  • you often see colors written in hexadecimal, with two digits for each color (8 bits)
    • still in RGB order
    • ff0000 is max red, no green or blue

3 Binary Search

3.1 Warmup

Write a function contains(v, x) that returns True is x is an element in v and returns False otherwise. Do not use the in operator.3

3.2 Guessing Game

  • Consider a number guessing game where you are trying to guess a number between 1 and 100.
    • What strategy would you use?
    • We could start by guessing 1, then 2, then 3, and so on. This would be a linear search strategy, just like contains used a linear search to find an element in a list
    • What if every time you guess, I tell you whether your guess is higher or lower than the number
    • A good way to take advantage of these new rules would be to guess right in the middle of the range of possible numbers (i.e., 50).
      • That way, if I say the number is higher, you can rule out the lower half of the range. If I say the number is lower, you can rule out the higher half of the range. You can continue this guessing in the middle strategy, each time ruling out half of the remaining numbers.
    • Since binary means 2 (why we use it as the name for a numbering system where the digits have 2 possible values), this strategy is called binary search

3.3 Implementation

  • How could we apply this binary search strategy to finding a number in a list?
    • We don't have another person to say higher or lower, so we will need some other way of narrowing our search.
    • In particular, when we check a number in the list, we need that to divide the list into two portions: one where all the numbers are larger and one where all the numbers are smaller.
    • The key property here is that the list needs to be sorted.
    • That way, when we check the number in the middle against the number we're looking for, we can narrow our search to just half the list.
      • That is, if target is greater than the number in the middle of a sorted list, we know we only need to search the upper half of the list.
      • Similarly, if target is less than the number in the middle of a sorted list, we know we only need to search the lower half.
def binary_search(nums, target):
    # we will assume nums is sorted in ascending order
    low = 0
    high = len(nums) - 1
    while low <= high: # stop when there are no more elements between low and high to check
        mid = (low + high) // 2 # get the middle index between low and high
        item = nums[mid]
        if target == item: # check if we've found target
            return True
        elif target < item: # we should look in the lower half of our range
            high = mid - 1 # move high index to one less than the mid index
        else: # we should look in the higher half of our range
            low = mid + 1 # move low index to one above the mid index
    return False

We can implement binary search recursively as well, using the recursive call to search the appropriate half of the list:

def binary_search_rec(nums, target):
    if len(nums) == 0:
        return False
    mid = len(nums) // 2
    if nums[mid] == target:
        return True
    elif target < nums[mid]:
        return binary_search_rec(nums[:mid], target)
    else:
        return binary_search_rec(nums[mid + 1:], target)

Footnotes:

1

1001

2

42

3
def contains(v, x):
    for elem in v:
        if x == v:
            return True
    return False

print(contains([1, 2, 3], 2)) # should print True
print(contains([1, 2, 3], 4)) # should print False