Divisibility
- For integers a\ne 0 and b, we will say that “a divides b” and write a\mid b if there is an integer c such that b=ac.
- Also “a is a factor of b” or “b is a multiple of a”.
- For example, 3\mid 9 but 3\nmid 10.
- We will use the concept of divisibility often, but for now, just a few key theorems.
- For integers a, b, and c,…
Theorem: a\mid b iff b/a is an integer.
Theorem: If a\mid b then a\mid bc for all c.
Theorem: If a\mid b and a\mid c, then a\mid (b+c).
Proof: If a\mid b and a\mid c, then there are integers d and e such that b=ad and c=ae.
Then, b+c=ad+ae=a(d+e). Thus, a\mid (b+c).∎
Theorem: If a\mid b and b\mid c, then a\mid c.
Proof: If a\mid b and b\mid c, then there are integers d and e such that b=ad and c=be.
Then, c=be=a(bd). Thus, a\mid c.∎
Corollary: If a\mid b and a\mid c, then a\mid mb+nc for all integers m and n.
Proof: From the above, we know that a\mid mb and a\mid nc. Then, a\mid mb+nc.∎
- Theorem: For an integer a and positive integer d, there are unique integers q and r with 0\le r \lt d such that a=dq+r.
- This theorem is called The Division Algorithm. It's not an algorithm, but that's still what it's called.
- If you refer to q as the quotient and r as the remainder, the theorem makes a lot of sense.
- If you divide a by d, you get quotient q and remainder r. The theorem says the exist and are unique.
- When we need these values, we will write a\mathop{\mathbf{div}}b = q and a\mathop{\mathbf{mod}}b = r.
- For example,
- 23\mathop{\mathbf{div}}5 = 4 and 23\mathop{\mathbf{mod}}5 = 3 and 23=5\cdot 4 + 3.
- 100\mathop{\mathbf{div}}7 = 14 and 100\mathop{\mathbf{mod}}7 = 2 and 100=7\cdot 14 + 2.
- 35\mathop{\mathbf{div}}5 = 7 and 35\mathop{\mathbf{mod}}5 = 0 and 35=7\cdot 5 + 0.
- Most programming languages have operators to get these values. On integers in C:
b/a
andb%a
. Theorem: For integers a and b with b\gt 0, we have a\mid b iff b\mathop{\mathbf{mod}}a = 0.
Proof: First, if a\mid b, then there is a n integer c such that b=ac. In the division algorithm, c is the quotient with a remainder of 0. Thus, b\mathop{\mathbf{mod}}a = 0.
Now if b\mathop{\mathbf{mod}}a = 0 then we have b=aq+0 in the division algorithm, so we see that a\mid b.∎
- You have probably used that fact in a program to test divisibility.
if ( n%2 == 0 ) { /* n is even */ … }
Modular Arithmetic
- For integers a and b, and a positive integer m, we will say that “a is congruent to b modulo m” and write a\equiv b\ (\text{mod } m) if m divides a-b.
Theorem: For integers a,b,m with m>0, a\equiv b\ (\text{mod } m) iff a\mathop{\mathbf{mod}}m=b\mathop{\mathbf{mod}}m.
Proof: First suppose that a\mathop{\mathbf{mod}}m=b\mathop{\mathbf{mod}}m=r. Then from the definition, there are integers p and q such that a=pm+r and b =qm+r. Now, a-b=pm-qm=m(p-q). Thus, we see that m\mid (a-b), so a\equiv b\ (\text{mod } m).
Now suppose that a\equiv b\ (\text{mod } m). [Left as a homework exercise. …] Thus a\mathop{\mathbf{mod}}m=b\mathop{\mathbf{mod}}m.∎
- In other words, a\equiv b\ (\text{mod } m) if they have the same remainder when divided by m.
Pseudorandom Numbers
- [An application of the divisibility stuff.]
- It is common to need random numbers in programs.
- In games to generate random behaviour in non-player characters.
- Statistical simulation/sampling.
- In cryptography to generate a key that it is impossible for an attacker to know (without just guessing every possible value).
- Problem: your computer is entirely deterministic. There's no way to get randomness out of it.
- Unless your computer has a hardware random number generator: a few processors and chipsets do.
- The OS can get a few “true” random values by taking keystroke timing, mouse movements, network I/O, etc. That's unguessable if done right, but limited: can't generate very many values because it doesn't have enough to work with.
- If you need random values in a program, you need something else.
- A pseudorandom number generator is an algorithm that generates values that are not random, but appear to be random enough.
- “Random enough”: are hard to predict, uniform (each value as likely as any other to be generated), seem to be random, etc.
- A pseudorandom number is definitely good enough for games, for example.
- Probably good enough for statistical sampling: as long as it's uniform it should do.
- Maybe not good enough for cryptography: “hard to predict” isn't the same as “impossible to predict”.
- One way to produce random numbers: a linear congruential generator. We choose four integers:
- A modulus m.
- A multiplier a with 2\le a \lt m.
- A increment c with 0\le c \lt m.
- A seed x_0 with 0\le x_0 \lt m.
- The linear congruential generator will generate a sequence of pseudorandom values x_n with
x_n = (ax_{n-1} + c)\mathop{\mathbf{mod}}m\,.
- From the definition of \mathbf{mod}, these values are clearly integers from 0 to m-1.
- Let's try it with m=100, a=41, c=19, and x_0=33:
\begin{align*}
x_0 &= 33 \\
x_1 = (41x_{0} + 19)\mathop{\mathbf{mod}}100 &= 72 \\
x_2 = (41x_{1} + 19)\mathop{\mathbf{mod}}100 &= 71 \\
x_3 = (41x_{2} + 19)\mathop{\mathbf{mod}}100 &= 30 \\
x_4 = (41x_{3} + 19)\mathop{\mathbf{mod}}100 &= 49 \\
x_5 = (41x_{4} + 19)\mathop{\mathbf{mod}}100 &= 28 \\
&\vdots \\
x_{98} = (41x_{97} + 19)\mathop{\mathbf{mod}}100 &= 35 \\
x_{99} = (41x_{98} + 19)\mathop{\mathbf{mod}}100 &= 54 \\
x_{100} = (41x_{99} + 19)\mathop{\mathbf{mod}}100 &= 33 \\
x_{101} = (41x_{100} + 19)\mathop{\mathbf{mod}}100 &= 72
\end{align*}
- Observations:
- Since x_n only depends on x_{n-1}, once we hit x_0 again, we'll enter a loop and generate the same values again.
- The best period of the loop we can hope for is m: we can only generate m distinct values before getting back to x_0.
- We should choose a large m.
- If we had chosen c=20 above, we would have only generated 5 values before looping.
- Choices of the constants matter a lot: choosing them badly makes the generator useless.
- This sequence is obviously predictable.
- If I tell you I just generated 71, you can tell me the next value.
- If you know the seed, you can predict all of the values.
- If you know I generated my private cryptographic key, and the next number generated was 35, you can figure out my private key without too much work.
- It would have been much harder to predict if I only showed you the first digit of each x_i: 7, 7, 3, 4, 2,… , 3, 5.
- If we have a little bit of “true” randomness, we can at least use that to generate the seed.
- … and most pseudorandom number implementations do.
- Linear congruential generators are a realistic pseudorandom number technique.
- Java's
java.util.Random
uses one with m=2^{48}. - Most C implementations use one with m=2^{31} or 2^{32}.
- In each case, they don't return all of the bits (just like the “first digit” example above).
- But it's not the only algorithm: Python, Ruby, R use the Mersenne twister algorithm.
- Java's