Lecture Overview

Problem 1

Assuming the following definitions, fill in the table.

a = b"hello world"
b = "hello world"
c = 0b1101 
d = 0x73 
Possible types are:
str, int, bytes, float
expressiontypevalue
a[1]
b[1]
c | 0x10
c & 0x10
chr(d ^ 0x40)
d >> 4
c / 2
c // 2
c % 7
(-c) % 7

Problem 2

Write a code bits.py so that the following code works as follows. Assume that the input is always 8 bits long.
>>> from bits import *
>>> a = 0b10110101
>>> pr(a)
dec: 181
hex: 0xb5
bin: 10110101
>>> b = zero_out_top(a,3)
>>> pr(b)
dec: 21
hex: 0x15
bin: 00010101
>>> c = set_one_at(a, 4)
>>> pr(c)
dec: 189
hex: 0xbd
bin: 10111101
>>> d = set_zero_at(c, 4)
>>> pr(d)
dec: 181
hex: 0xb5
bin: 10110101

Problem 3

What is the output of the following code?
import struct
data = struct.pack("<BH", 193, 2345)
for d in data:
  print("f{d:02x}", end=" ")

Problem 4: Type Conversions

Int → String

If you change a number into a string, you can simply call str() function.

>>> n = 10
>>> n
10
>>> s = __________
>>> s
'10'
Note that b[0] contains the ASCII code for character '1', and b[1] for character '0'.

Int → Bytes

Sometimes, you may want to pack a number into raw bytes. As we saw above, you can use struct.pack, or you can use to_bytes() function.

>>> n = 12345678901234567890
>>> b = _______________________
>>> b
b'\x00\x00\xabT\xa9\x8c\xeb\x1f\n\xd2'
  • The first argument to to_bytes() is telling it how many bytes to use for packing the number. In the above example, the number is encoded in 10 bytes.
  • The second argument is endian.

Int → Hex String

You may want encode a number into a hex string. In that case, you can use the hex() function,

>>> n = 12345678901234567890
>>> s = ______________
>>> s
'0xab54a98ceb1f0ad2'

Bytes → Int

Sometimes, you may want to decode raw bytes into a number. For this, you can use int.from_bytes() function.
  • The first argument to from_bytes is a bytes object.
  • The second argument is endian.

>>> b = b'\x00\x00\xabT\xa9\x8c\xeb\x1f\n\xd2'
>>> n = __________________
>>> n
12345678901234567890

Bytes → String

You can call decode() function to decode a bytes object into a string.

>>> b = b'hello world'
>>> s = ______________
>>> s
'hello world'

Bytes → Hex String

You can use hex() function to convert a bytes object into a hex string.

>>> d =  b"\x01\xfa\x03"
>>> h = ______________
>>> h
'01fa03'

String → Int

If you change a string into a number, you can simply call int() function.

>>> s = "1234567890"
>>> n = _____________
>>> n
12334567890
>>> b = b"12334567890"
>>> n = ___________
>>> n
12334567890

String → Bytes

In addition, you can use encode() function to convert a string into a bytes object.

>>> s = '10'
>>> b = _____________
>>> b
b'10'

Hex String → Int

You can call int() function with an additional argument to convert a hex string into a number.

>>> s = '0xab54a98ceb1f0ad2'
>>> n = _________________
>>> n
12345678901234567890

Hex String → Bytes

You can call bytes.fromhex() to convert a hex string into a bytes object.

>>> s = '0xab54a98ceb1f0ad2'
>>> b = ______________________
>>> b
b'\xabT\xa9\x8c\xeb\x1f\n\xd2'
Note: The function fromhex() doesn't like "0x" prefix. So, using s[2:], we can skip that prefix.

Additions of Hex Numbers

Adding hex (base-16) numbers are essentially the same as adding base-10 numbers. Just remember:
[hex]    
   7    
+  5   
-----  
   c   
[hex]    
   8    
+  6   
-----  
      
[hex]    [decimal]
   a                 10
+  b                 11
-----   ---------------
  15     21 = 1*16 + 5 
[hex]  
   c
+  5 
-----

[hex]  
   f
+  d 
-----

Now, let's move on to adding numbers having multiple hex digits.
[hex]    
   abcd
+  1234
-------- 

step 1: d + 4 = 0x11  (carry!)

     1 
   abcd
+  1234
-------- 
      1

step 2: 1 + c + 3 = 0x10 (carry!)

    11 
   abcd
+  1234
-------- 
     01

step 3: 1 + b + 2 = e (no carry)

    11 
   abcd
+  1234
-------- 
    e01

step 4: a + 1 = b

    11 
   abcd
+  1234
-------- 
   be01
Evaluate the following.
  cdef
+ 4567
-------