Previous Section Table of Contents Next Section

Print the Prime Factors of a Number

This function prints out the prime factorization of a number passed as an argument.

It uses a simple algorithm that loops through all possible factors (between 2 and the number itself), from smallest to largest, and divides the number by each factor that is found until it reaches 1. The factors should be printed out on one line, with a space separating each factor. Note: The inefficiency of the algorithm is not considered a bug.

Source Code


 1.     # number to factor is passed as an argument

 2.     $number = $ARGV[0];

 3.

 4.     # $left is the unfactored part that remains

 5.     $left = $number;

 6.

 7.     # loop through all possible factors

 8.     foreach $test (2..$number) {

 9.

10.         # exit when no factoring left to do

11.         if ($left == 1) {

12.             last;

13.         }

14.

15.         # does $test divide $left?

16.         if ($left % $test == 0) {

17.

18.             $left /= $test;

19.

20.             # print a space between factors

21.             unless ($first) {

22.                 print(" ");

23.             } else {

24.                 $first = 1;

25.             }

26.

27.             # now print the factor

28.             print ("$test");

29.

30.             # try this factor again

31.             redo;

32.         }

33.     }

34.

35.     print ("\n") unless $first;


Suggestions

  1. Under what circumstances will the foreach loop on lines 8-33 exit by hitting the end of its list, as opposed to the explicit last statement on line 12?

  2. Prove to yourself that the algorithm employed is correct.

  3. When should the final "\n" not be printed by line 35?

Hints

Walk through the program with the following parameters:

  1. A value that should print nothing: 1

  2. A prime number: 7

  3. A number with unique prime factors: 30

  4. A number with repeated prime factors: 36

Explanation of the Bug

The variable $first is not used properly. The intention of this variable is to distinguish the first prime factor from the rest because, after the first factor, a space should be printed before each succeeding factor. However, because the variable is not initialized, it begins as logically false, which means that $notfirst would be a better name. Ignoring the variable name, this is an A.logic error. The check on line 21


unless ($first) {


is true to begin with, and because the else clause of this if is the only place that first is ever set to 1, $first remains undef (therefore, false) forever. As a result, a space is printed in front of every factor, including the first. The statement on line 35 also makes the same mistake:


print ("\n") unless $first;


This is attempting to only print out the "\n" if any factors were found, but it winds up always printing it since $first always remains undef.

One fix is to change the unless to an if on line 21


if ($first) {


and line 35


print ("\n") if $first;


This preserves the misnaming of the variable. Another approach is to add an initialization statement to set $first to 1 at the beginning of the program, and then change line 24 to set $first to 0, which matches the name of the variable to its meaning.

    Previous Section Table of Contents Next Section