The basic example of how numbering systems work:

Base 10:

53 = **5***10 + **3**

192 = **1***100 + **9***10 + **2**

693914 = **6***$10^5$ + **9***$10^4$ + **3***$10^3$ + **9***$10^2$ + **1***$10^1$ + **4***$10^0$

Or

693014 = 6*$\mathbf{10}^5$ + 9*$\mathbf{10}^4$ + 3*$\mathbf{10}^3$ + 0*$\mathbf{10}^2$ + 1*$\mathbf{10}^1$ + 4*$\mathbf{10}^0$

This "10" means that we are currently using decimal numbers, or base 10.

Changing this number means changing the base.

53 = **5***6 + **3** (which is 33 in base 10)

100 = **1***36 + **0***6 + **0** (which is 36 in base 10)

192 = ??? (there is no number 9 in base 6, there are only numbers 0, 1, 2, 3, 4, 5)

23240400 = **2***$6^7$ + **3***$6^6$ + **2***$6^5$ + **4***$6^4$ + **0***$6^3$ + **4***$6^2$ + **0***$6^1$ + **0***$6^0$ (which is 720720 in base 10)

1010 = **1***8 + **0***4 + **1***2 + **0***1 (which is 10 in base 10)

110111 = **1***32 + **1***16 + **0***8 + **1***4 + **1***2 + **1***1 (which is 55 in base 10)

For any base there number of available digits equals the base. So, only two digits (0 and 1) for base 2, 10 digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) for base 10.

Therefore, extra symbols for "10, 11, 12, 13, 14 and 15" are needed for base 16. Latin letters A, B, C, D, E and F are used as these digits.

10AB = **1***16^3 + **0***16^2 + **A***16^1 + **B***16^0

Converting to base 10:

**1***$16^3$ + **0***$16^2$ + **A***$16^1$ + **B***$16^0$ =

**1***4096 + **0***256 + **A***16 + **B***1 = 4096 + 10*16 + 11 = 4267

So, 10AB in base 16 is 4267 in base 10.

To convert a number from some other base to base 10, you represent the number as a mathematical expression. For a number "xyzzy" in some base b the expression is

**x***$b^4$ + **y***$b^3$ + **z***$b^2$ + **z***$b^1$ + **y***$b^0$

Then you perform multiplications, take the sum are get the number in base 10.

In [ ]:

```
original_number = '2324'
original_base = 6
answer = 0
# your code
# dec_number =
print(answer)
# there is a default python way of converting any base to decimal:
number = int(original_number, original_base)
print(number)
# Do not use it here
```

Convert the following numbers to base 10:

100, 244, 121 from base 6,

10101101 from base 2,

F4, AD from base 16.

To convert numbers to base 10 you use multiplication and compute the sum. To convert numbers from base 10 to other bases you use division.

For example, converting the number 53 to base 6 will look like this:

53 // 6 = 8 (+**5** as a remainder)

8 // 6 = 1 (+**2** as a remainder)

**1** is less than 6

The answer is 125. We can check if it's the correct answer:

125(6) = **1***36 + **2***6 + **5** = 36 + 12 + 5 = 53(10)

Converting the same number 53 to binary:

53 // 2 = 26 (+**1** as a remainder)

26 // 2 = 13 (+**0** as a remainder)

13 // 2 = 6 (+**1** as a remainder)

6 // 2 = 3 (+**0** as a remainder)

3 // 1 = 1 (+**1** as a remainder)

**1** is less than 2

The result is 110101.

The last example, converting 4267 back to base 16.

4267 // 16 = 266 (+**11** as a remainder)

266 // 16 = 16 (+**10** as a remainder)

16 // 16 = 1 (+**0** as a remainder)

**1** is less than 16

The answer is 1 0 10 11. Or 10AB.

In [ ]:

```
original_number = 1000
to_base = 8
answer = ''
# use this line:
# answer = str(remainder) + answer
# your code here
if not answer:
answer = '0'
# result should be a string
print(answer)
number = int(answer, to_base)
print (number)
```

Computers store all information in binary, so you have to understand how binary works if you want to better understand the low-level processes in computers.

Binary is inconvenient in some respects. Particularly, even small numbers are represented as long strings in binary.

110111(2) is 55(10)

10101101100111(2) is 11111(10)

Luckily, it is quite easy to convert binary to base 16 and back.

```
Base 2: 11 0111
Base 10: 3 7
Base 16: 3 7
```

And

```
Base 2: 10 1011 0110 0111
Base 10: 2 11 6 7
Base 16: 2 B 6 7
```

2 binary digits always convert to a single hexadecimal digit, so you can do the conversion by groups of 4 digits.

Bytes of computer information are groups of 8 binary digits, and they can be represented as two hexadecimal digits.

Octal numbering system is also used in some cases. An octal digit can represent 3 binary digits.

```
Base 2: 10 101 101 100 111
Base 8: 2 5 5 4 7
```

This way you can easily convert numbers between binary and any other "power of two" base.

An example of converting backwards:

```
Base 16: 9 5 A 5 A
Base 10: 9 5 10 5 10
Base 2: 1001 0101 1010 0101 1010
```

*Base 10 is used just to illustrate the base 16 digits, this method doesn't help with conversion to base 10.*

Convert FF5733 to binary and then to octal.

Convert 10715526 (*8*) from octal to binary and then to base 16.

Earlier there were mostly examples of conversion between decimal and other bases. There wasn't any reason for this other than base 10 being the default base for us and the base we are used to. It's possible to move all arithmetic and all math to other bases.

You can add up numbers just like in base 10. You add up digits, then, if the result is larger or equal to the base, you carry 1 to the next digit.

```
111 1
010010101101 +
100011100100
============
110110010001
```

The first row marks places where 1 is carried in the sum.

Now base 6:

```
1 11
2352 +
4144
====
10540
```

Just like for base 10, you need a multiplication table for all 1-digit numbers so it is easier to perform multiplication.

For binary the table is quite simple:

```
| 0 | 1 |
0 | 0 0 |
1 | 0 1 |
```

For base 6 it's more complex:

```
| 0 | 1 | 2 | 3 | 4 | 5 |
0 | 0 0 0 0 0 0 |
1 | 0 1 2 3 4 5 |
2 | 0 2 4 10 12 14 |
3 | 0 3 10 13 20 23 |
4 | 0 4 12 20 24 32 |
5 | 0 5 14 23 32 41 |
```

Using such a table for a particular base, you can multiply numbers of this base just like decimals.

```
1101 *
110
=======
0
1101 +
1101
=======
1001110
```

Try multiplying 1011 by 1001 in binary.

One of the applications where binary directly comes into play is network routing.

IP address is an important part of the network structure. Usually it is written as 4 decimal numbers separated by dots:

208.80.154.224 - an IP address used by Wikimedia Foundation.

Sometimes several IP addresses are united in a subnetwork, where they have a fixed prefix and differ only by the last several binary digits.

These masks can be written as "/25" or 255.255.255.128. In this example, both these masks mean that the first 25 binary digits of an IP address stay the same and the last 8 ones change.

```
Address: 11010000.01010000.10011010.11100000
Mask: 11111111.11111111.11111111.10000000
Network: 11010000.01010000.10011010.10000000
```

By applying the mask to the address (that is, using an "AND" operation, or multiplying each digit of an address to a digit of a mask) you get a network prefix.

Try applying the masks 255.255.255.192 and 255.255.248.0 to the following addresses:

111.49.45.105

39.134.166.136

203.213.41.232

Python has a default way of converting numbers from other bases to base 10 as a part of the function `int`

. However, if you want to convert numbers to other bases, you have to implement the algorithm yourself.

Solve this task after practicing tasks on loops and conditional statements.

In [ ]:

```
alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
original_number = '255'
from_base = 10
to_base = 16
result = ''
# convert the number to base 10
number = int(original_number, from_base)
# your code here
print(result)
```