Python/Prime factorization

Topics covered: prime factorization, flowcharts, Python dictionaries

Here we learn how a Python dictionary can help express an integer as a product of prime numbers. There are two things each student should know about the code we are about to examine:


 * A serious Python programmer would instead download a package that already has a function for prime factorization. Two promising candidates are pypi.org/project/primefac and www.sympy.org/.
 * A simpler version of this same program does not use the Python dictionary. It can be found at Trial division..

Lacking the wherewithal to seize upon either of these opportunities, I googled "python prime factorization", and found many codes, and selected the one we shall examine for two reasons:
 * I wanted a program that counts repeated factors to later write the factored form in wikitext with exponents.
 * I didn't understand the Python source code and wanted to master it to fully understand how python dictionaries are used.

A good student exercise would be to modify this code so that it runs approximately twice as fast. This is accomplished by considering only odd numbers in the search for prime factors of N. The table below illustrates the present version of the source code's "wasted" efforts to see if 4 and 6 might be prime factors of 1550. The table also illustrates the efficiency of dividing a candidate integer into the number $$n$$, which soon becomes much smaller than $$N.$$ It took only eight (8) steps to factor $1550$ into prime numbers.

Python code
‎

Discussion
With one extra line, a print command will display the dictionary. From the fact that Python decided to print $31$ as $31.0$, we know that this dictionary is taking the keys (2, 5, 31) to be floating point numbers. Python permits such a casual attitude regarding the mixing number types. This makes it easier to program python, but perhaps more difficult to sort out such misunderstandings after the program has been written. print(dict) {2: 1, 5: 2, 31.0: 1}

Line 15: while k**2 <= n:
This is an important line because it permits the termination of the search before one might think. I leave it as an exercise for the student to learn why any value of k larger than the square root of n will never be the next factor of N. It is also left to the student to understand the fact that the time to find the factors can be cut nearly in half if we modify line 17 and increase k by 2 (instead of 1), and why this larger step cannot be taken until after k=2 has been considered.

Lines in the code that might seem confusing
The code uses two clever tricks that might seem confusing. I lack the formal training in programming to know whether such cleverness would be perceived as a flaw. I know that programmers are allowed to be clever, and I know that clear programs are better than confusing programs. The fact that these tricks confused me does not necessarily mean they should be avoided.

And the nice thing about both sources of confusion is that they taught me something about python.

Line 16: if n%k might seem backwards
Python follows a common practice of interpreting the number 1 to be True and 0 to be False. But Python also accepts any non-zero number as True. Here n%k denotes nmod k, which is the remainder when n is divided by k. If there is no remainder the "if" condition is not satisfied and the code stipulates that the next value of k is attempted. Any number not equal to zero is interpreted as the "if" condition being satisfied, meaning that k is a divisor of n (in that case, we replace n with n/k.)

This might be good coding, but it seems to me that it would have been better to construct it along the lines of " " or even " ".

Lines 21-23 and 29-31: A failed attempt to change the value of a key
In this code fragment, we ask if a given value of k has already been identified as a factor. But instead of "asking" if k has been declared a key in the dictionary, an attempt is made to change the value of k. If that attempt fails (because k is not among the dictionary's keys), then k is added to the list of keys, with a value of 1 (a value of 1 indicates that at this point, k, but not k2 has been established to be a factor of n.)

Again, there might be nothing wrong with using a key error like this. But the code would have been easier for me to follow if the if statement simply called the question of whether k was a key in dict.

Sample output with a large number
Sometimes you have to wait a few minutes to factor a number this large. But usually, it comes out in just a few seconds. I would imagine that a number that was the product of only two roughly equal prime numbers would take forever because k=k+1 must be repeated a virtually infinite number of times. This number came quickly: Enter a positive integer you wish to factor into prime numbers: 99283428376482768916467328912876456416375474272263423467896879187289499287374899 99283428376482768916467328912876456416375474272263423467896879187289499287374899= (619**1) * (688**1) * (768**3) * (1024**17) * (64853**1) * (5302548928**1) The dictionary is: {619: 1, 688: 1, 768: 3, 1024: 17, 64853: 1, 5302548928.0: 1} Type 1 for another integer, 0 to terminate.

DO NOT TRY TO FACTOR A NUMBER THIS LARGE UNLESS YOU ARE WILLING TO INTERUPT YOUR PYTHON PROGRAM.

Keep in mind that the universe is only about $4.4\times10^{26}\text{nanoseconds}$ old.

The number shown rounds up to 1080. It is not likely that any computer will ever count that high. If the number to be factored consists of two prime numbers that are close to 1080, the code will iterate up to k coming close to 1040. The inability of any computer to perform that many iterations helps explain how cryptocurrency works. The owner of a cryptocurrency can have all of their information made public by posting something with the properties of the product of two very large prime numbers. The product is made public and anybody with knowledge of one of the products can claim ownership of the funds.

On the other hand, if you lose that information, nobody on earth can retrieve it for you.