
| FUNCTION:
PrimeFactorSum(). Pass an integer to this function
and it will generate all its prime factors, totalise them, and return
the sum to the calling routine. Note that this function uses another function: IsPrime(). Obviously, you must include IsPrime() with PrimeFactorSum() for the latter to work. To obtain a copy, click here now. It's up to you what data type you make the argument, depending on the type of integer you want to process. |
|
Type
|
Exponent
of 2 |
Value
|
| int | 230 | 1073741824 |
| uint | 231 | 2147483648 |
| int64 | 261 | 2305843009213693952 |
| uint64 | 262 | 4611686018427387904 |
| Declaring the function must be done like
this: declare PrimeFactorSum(c: int) (or whatever integer type you want). Here's the code: sub PrimeFactorSum(c) ' finds the prime factors of argument c ' and returns their sum def sum, factor: int sum = 0: 'intialise sum to zero ' look for factor 2 factor = 2 do if c % factor = 0: '2 is a factor sum = sum + factor: 'add it to sum c = c/factor: 'divide c by 2 endif until c % factor <> 0: 'until 2 not a factor ' look for factors greater than 2 factor = 3 do if IsPrime(factor): 'ensure factor is prime if c % factor = 0: 'is it a factor? sum = sum + factor: 'add it to sum c = c/factor: 'divide c by factor else factor = factor + 2: 'get next odd factor endif else factor = factor + 2: 'get next odd factor endif until c = 1: 'no more factors possible return sum |
| There are only two local
variables. Variable sum, which
holds the sum of the prime factors. This is initialised to zero,
and gradually increases as the function progresses, until it holds the
full sum. Variable factor
holds the factor currently being tested. In the description of the code which follows, I have applied line numbers to make it easier to follow. Here they are: |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def
sum, factor: int sum = 0: 'intialise sum to zero factor = 2 do if c % factor = 0: '2 is a factor sum = sum + factor: 'add it to sum c = c/factor: 'divide c by 2 endif until c % factor <> 0: 'until 2 not a factor factor = 3 do if IsPrime(factor): 'ensure factor is prime if c % factor = 0: 'is it a factor? sum = sum + factor: 'add it to sum c = c/factor: 'divide c by factor else factor = factor + 2: 'get next odd factor endif else factor = factor + 2: 'get next odd factor endif until c = 1: 'no more factors possible return sum |
| Now
for a line-by-line exegesis of the code. |
| 1 |
def sum, factor: int. Defines the two local variables to be used by the function, already described above. |
| 2 |
sum = 0. Initialises variable sum to zero. By the time sum is returned to the calling routine, it will hold the PFS (prime factor sum) of the argument. |
| 3 |
factor = 2. Variable factor is initialised to two. This is the lowest possible prime factor of any number (and the commonest). Because it's the only even-numbered prime factor, it's dealt with separately as a special case. |
| 4 |
do.
Opens the DO loop associated with the case where the prime factor
is 2. Lines 4 through 9 deal exclusivesly with this case . |
| 5 |
if c % factor = 0. A simple way to find out if a prime number is a prime factor of another, larger number is to divide the larger number by the smaller and check for a remainder. If there is no remainder, we have found a prime factor. This line makes the check by using integer arithmetic. The percentage (%) sign means "make a division and discard all the result except for the remainder. So this line can be paraphrased as "Is the remainder when dividing argument c by variable factor zero?" |
| 6 |
sum = sum + factor.
This line is only executed if the answer to the question in line 5 is
"yes." That means that variable factor
(2 in this case) is a prime factor of argument c. So we can add factor to variable sum, which is totalising all the
prime factors of the argument. |
| 7 |
c = c/factor.
Line 7 is critical to the function. Having found a prime factor
of argument c, it's
necessary to reformat c so
that the next prime factor can be investigated. Remember, it
could be the same number. For instance, the prime factors of 8
are 2, 2, and 2. The "reformatting" is simple: just divide c by the prime factor itself and start again. Note that we can be certain this division is possible because the check in line 5 told us there would be no remainder. Take a closer look at the example of 8 above. When the first prime factor, 2, has been found, add it to sum. The latter was initialised to zero, so it now equals 2. Now divide c by 2 to leave 4. 2 is again a factor of 4, so it's added to sum making sum equal 4. c is once again divided to 2. 4/2 = 2, so c is now 2. 2 is a prime factor of 2, so it's added to sum to make sum equal 6. If we go on to divide c by 2 again, there will be a remainder, so the process stops, giving PFS(8) = 6, the correct answer. |
| 8 |
endif. Housekeeping - closes IF-ENDIF clause. |
| 9 |
until c % factor <> 0. Line 9 marks the end of the DO loop associated with prime factor 2. A decision must be made: should the DO loop be executed again, or is it time for the code to move on to the next line? The repeated divisions made in the example above depended on the fact that there was never a remainder when c was divided by factor, which means factor is a prime factor of c. As soon as a remainder is encountered, we know that factor cannot be a prime factor of c. So line 9 can be expressed this way: "If variable c divides exactly by factor, execute the DO loop again; if not, quit the loop." |
| 10 |
factor = 3. This line is only reached after all the prime factors 2 have been found and totalised in sum. Now we move on to the first odd prime factor, 3. All subsequent prime factors to be investigated will be odd, since 2 was the only prime factor there is. So variable factor is set to 3 ready to work on the odd prime factors. |
| 11 |
do. Opens the DO loop associated with odd prime factors only. |
| 12 |
if IsPrime(factor). Now that we're working with odd number values for factor, we have to be careful: not all odd numbers are prime. for example, 9 isn't prime but 11 is, and so on. Only prime numbers can also be prime factors, so a check on primality is made, using function IsPrime(). As explained in the introducty remarks above, you will have to include this function with the PrimeFactorSum() code. A link is provided to obtain the code. This line is therefore effectively saying "If the current value of variable factor is prime, execute the code in lines 13 through 18; if not, go to line 19 to be given alternative instructions." |
| 13 |
if c % factor = 0. Works in exactly the same way as line 5, except that the value of factor will now be an odd number instead of 2. |
| 14 |
sum = sum + factor.
This line is only executed if the answer to the question in line 5 is "yes."
That means that variable factor (2 in
this case) is a prime factor of argument c. So we can add factor to variable sum, which is totalising all the prime factors
of the argument. |
| 15 |
c = c/factor. This command can be paraphrased as "Divide the value stored in argument c by the value stored in variable factor and save the result in c, over-writing what was already stored in there." It's reducting c's value ready for the next factor test. |
| 16 |
else.
If it was found in line 13 that the current value in variable factor didn't divide exactly into c's current value, we need to take
alternate action. The else
here
prepares for that. |
| 17 |
factor = factor + 2. The alternate action is to try the next higher permissible value for factor. Since we're only dealing with odd numbers now, factor is incremented by 2 to keep it odd. |
| 18 |
endif. Housekeeping - closes inner IF-ENDIF clause. |
| 19 |
else.
Housekeeping - provides alternate action if line 12 returns FALSE, that
is, the current value of factor
in that line wasn't prime. |
| 20 |
factor = factor + 2. And this is the alternate action to line 12 - try the next higher value of factor which is still an odd number. |
| 21 |
endif.
Housekeeping - closes the IF-ELSE-ENDIF clause originating in line 12. |
| 22 |
until
c = 1.
We are dividing c by each
prime factor it finds. Eventually, the last division will leave a
remainder of 1. When this happens, all the prime factors have
been found. Line 22 is therefore providing a test whose result
decides whether to execute the odd-number DO loop again or move
on. Thus, a paraphrase of line 22 could be "If the value of the
recently-divided c is unity,
move on to the next line of code; if not, re-execute the DO loop from
line 11 again." |
| 23 |
return
sum.
When the code reaches this line, all prime factors have been found and
totalised into variable sum.
All that remains to be done is to return this value to the calling
routine, and line 23 does just that. |
| Finally,
let's do a table of working results for an argument of, say, 84. |
| c |
factor |
c/factor |
PF's |
sum |
comments |
| 84 |
2 |
42 |
2 |
2 |
Using
line 4 DO loop |
| 42 |
2 |
21 |
2 |
4 |
Using line 4 DO loop |
| 21 |
3 |
7 |
3 |
7 |
Using line 11 DO loop |
| 7 |
7 |
1 |
7 |
14 |
Using line 11 DO loop |
| 1 |
c = 1: finished |
| Note
the way in which the original argument c is steadily reduced from 84 to 1
as the function progresses. At the same time, the value in
variable sum, which was
initialised to zero, gradually increases to 14. If you look down
the PF (prime factors) column, you can see how they're discovered in
order: 2, 2, 3, 7. |
MAIN MENU
HOW DOES IT WORK?
Site design/maintenance: Dave Ellis E-mail me!
Last Updated: February 5th, 2010.