By longstanding convention, basically every society on Earth writes numbers in base 10, otherwise known as decimal. When we write a number such as 1985, we actually mean a sum of powers of 10:
1985 = 1 · 103 + 9 · 102 + 8 · 10 + 5
We will now discuss simple algorithms that can split an integer (e.g. 1985) into a series of decimal digits (1, 9, 8, 5), and can combine a series of decimal digits into an integer.
To split into digits, we first notice that for any integer i,
i mod 10 is the last digit of i
i div 10 is the number formed by all digits of i except the last
We can see this mathematically by factoring the expansion of 1985 above:
1985 = 1 · 103 + 9 · 102 + 8 · 10 + 5 = 10 (1 · 102 + 9 · 10 + 8) + 5
From this factoring it is evident that 1985 mod 10 = 5 and 1985 div 10 = (1 · 102 + 9 · 10 + 8) = 198.
So we can write a simple loop that extracts digits from an integer in succession. In Python:
n = int(input('Enter n: ')) while n > 0: d = n % 10 n = n // 10 print('digit: ', d)
For example:
Enter n: 1985 digit: 5 digit: 8 digit: 9 digit: 1
To combine a series of digits into a number, we first notice that we can append a decimal digit d to an integer n using this formula:
n' = 10 · n + d
For example, if n = 198 and d = 5, then n' = 10 · 198 + 5 = 1985.
So we can write a simple loop that reads a series of digits, one per line, and combines them into an integer. The user will enter '-1' when there are no more digits. In Python:
n = 0 while True: d = int(input('Digit: ')) if d < 0: break # end of input n = 10 * n + d print('n is', n)
The program behaves like this:
$ py joinDigits.py Digit: 1 Digit: 9 Digit: 8 Digit: 5 Digit: -1 n is 1985 $
We use base 10 by convention, but of course the number 10 is arbitrary. We would now like to work with numbers written in non-decimal bases, i.e. bases other than 10. For example, consider base 5. In the base 5 system, every digit has a value from 0 to 4. Consider the number
20315
Here, the subscript 5 means that the number is written in base 5. (In this course, you may assume that any number written without a subscript is in base 10.)
The decimal value of the base-5 number above is
2 · 53 + 0 · 52 + 3 · 5 + 1 = 26610
Base 2 (binary) is especially common in computer programming. Here are the first natural numbers in base 2:
02 = 010
12 = 110
102 = 210
112 = 310
1002 = 410
1012 = 510
1102 = 610
1112 = 710
10002 = 810
We also often use base 16 (hexadecimal), in which we have extra digits A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. For example,
FF16 = 25510 because 15 · 161 + 15 · 160 = 240 + 15 = 255
Internally, computers usually do not store numbers in base 10. (Instead, they are actually stored as a sequence of bytes, though you don't need to worry about that too much for the moment). Python functions such as print() internally perform arithmetic operations to produce decimal digits from a number. Similarly, functions such as int() use arithmetic to join decimal digits into a number.
Previously we saw algorithms that can split an integer into decimal digits, and join a series of decimal digits to form an integer.
Let's now generalize those algorithms to work with non-decimal bases. Actually the change is trivial: we simply change the constant 10 in our code!
For example, previously we saw this program to print a number's decimal digits:
n = int(input(
'Enter n: '
))
while
n >
0
:
d = n %
10
n = n //
10
print(
'digit:'
, d)
Let's modify it to print a number's binary digits. We only need to change the constant 10 to 2:
n = int(input(
'Enter n: '
))
while
n >
0
:
d = n %
2
n = n //
2
print(
'digit:'
, d)
Let's run the program:
Enter n: 43 digit: 1 digit: 1 digit: 0 digit: 1 digit: 0 digit: 1
The digits are generated in reverse order. The program's output means that
1010112 = 4310
This is because
1 · 25 + 0 · 24 + 1 · 23 + 0 · 22 + 1 · 2 + 1 = 32 + 8 + 2 + 1 = 43
We can modify the program to combine the digits into a string. Because the digits are generated in reverse order, we must prepend to the string at each step to end up with the digits in the correct order.
n = int(input('Enter n: ')) s = '' while n > 0: d = n % 2 n = n // 2 s = str(d) + s # prepend digit to string print('in base 2:', s)
Let's run it:
Enter n: 43 in base 2: 101011
Similarly, above we saw a program that reads a series of decimal digits and joins them into an integer:
n = 0 while True: d = int(input('Digit: ')) if d < 0: break # end of input n = 10 * n + d print('n is', n)
We can easily modify this program to work another base. Once again, let's change 10 to 2:
n = 0 while True: d = int(input('Digit: ')) if d < 0: break # end of input n = 2 * n + d print('n is', n)
Now we run the program:
$ py hello.py Digit: 1 Digit: 0 Digit: 1 Digit: 0 Digit: 1 Digit: 1 Digit: -1 n is 43
The program has read the binary digits of 1010112 and combined them into the number 43.
To convert from base B to base C, you can
Combine the digits in base B into an integer. (By the way, in this step students sometimes think that they are "converting to base 10", but that's not true. An integer such as a Python int is not stored internally in base 10. It's best to think of it as a mathematical integer that's not in any base.)
Split the integer into digits in base C.
As we know from mathematics, a prime number is an integer greater than 1 whose only factors are 1 and itself. For example, 2, 7, 47 and 101 are all prime.
We would now like to write a program that tests whether a given number is prime. To do this, we will use a simple algorithm called trial division, which means dividing by each possible factor in turn. (By the way, there also exist more efficient algorithms for primality testing, though they are more complex. You may encounter these in more advanced courses.)
Here is a naive implementation of trial division:
n = int(input('Enter n: ')) prime = True i = 2 while i < n: # loop from 2 .. (n - 1) if n % i == 0: prime = False break i += 1 if prime: print('n is prime') else print('not prime')
This works fine, but is inefficient because it may need to test all integers from 2 up to (n – 1). When n is large, this can take a long time.
Actually for a given n we need test only the values up to √n, i.e. the square root of n. To see this, consider the following fact. If ab = n for integers a and b, then either a ≤ √n or b ≤ √n. Proof: Suppose that a > √n and b > √n. Then ab > √n ⋅ √n = n, a contradiction. So either a ≤ √n or b ≤ √n.
It follows that if we have tested all the values from 2 through √n and none of them divide n, then if ab = n we must have a = 1 or b = 1. And so n is prime.
So we can make our program far more efficient by replacing the statement
while i < n:
with
while i * i <= n:
Now the loop will stop as soon as i > √n.