Novice programmers often believe that a program is either right or wrong. This comes from a false sense of security provided by the compiler. If it compiles it must be correct. Not so. Scowen and Ciechaniwicz [1] pose seven degrees of correctness for a program. We will look at these seven degrees, using a program to calculate factorials as an example.
1. Nonsense
These programs are not syntactically correct. The compiler is usually adept enough to find these problems.
1 #include <stdio.h>
2
3 int main(void)
4 {
5
6 double fact
7 for (i=2; i<100; i=i+1)
8 fact = fact * i;
9 printf(“Factorial = %d”, fact);
10 return 0;
11 }
This program contains a whole series of syntax errors:
- Line 5: No declaration for the variable i, used in line 7.
- Line 6: missing semicolon
- Line 9: %d used to print a double.
The program should look like:
1 #include <stdio.h>
2
3 int main(void)
4 {
5 int i;
6 double fact;
7 for (i=2; i<100; i=i+1)
8 fact = fact * i;
9 printf(“Factorial = %f”, fact);
10 return 0;
11 }
2. Illegal
These programs are syntactically correct but their actions are undefined at runtime. For example:
1 #include <stdio.h>
2
3 int main(void)
4 {
5 int i;
6 double fact;
7 for (i=2; i<100; i=i+1)
8 fact = fact * i;
9 printf(“Factorial = %f”, fact);
10 return 0;
11 }
When this program runs, we’ll get an answer, but it won’t be correct, because the value of fact was never initialized. Line 6 in the program should read:
6 double fact=1.0;
Another good example is the “array out of bounds” error that occurs in languages such as C.
3. Almost Working
The program gives the correct answer sometimes, not always. Such programs are sometimes described as 90% complete. For example:
1 #include <stdio.h>
2
3 int main(void)
4 {
5 int i, n=5;
6 double sum=0.0, a[5]={1,2,3,4,5};
7 for (i=0; i<n; i=i+1)
8 sum = sum + a[0];
9 printf(“Sum = %f”, sum);
10 return 0;
11 }
This program really only works when the value of n=0, such that the value of a[0] is summed. If n has any other value, the result is always a multiple of a[0], as there is no variable index used.
4. Fragile
These programs are syntactically correct and output the correct answer with valid input data. But illogical data will result in the program going nut-so. Consider the following program which divides one number by another.
1 #include <stdio.h>
2
3 int main(void)
4 {
5 double num, den, div;
6 scanf(“%lf %lf”, &num, &den);
7 div = num / den;
8 printf(“div = %f”, div);
9 return 0;
10 }
This program works when the denominator (den) does not equal zero. If it does equal zero, then a divide-by-zero error occurs.
5. Suspicious
Programs that are syntactically and semantically correct, but contain operations which have no logical effect. The program contains operations for no apparent reason. Many modern compilers check for used variables, but don’t detect variables which are assigned a value, but never used beyond that. Consider the following example of a function which calculates the area of a circle, given the radius:
double area(double radius)
{
double circ;
circ = 2.0 * pi * radius;
return pi * radius * radius;
}
The calculation of the circumference (circ) in the function is superfluous – it is never used beyond the assignment.
6. Wrong
A program may be correct, robust and never fail, yet it might be wrong because the client asked for a different function to be calculated. For example calculating a mean instead of a median, the measure in the specifications. Consider the case of calculating arithmetic versus geometric means in investment returns. If the returns for five years were 12%, 9%, 27%, 5% and -16%, the arithmetic mean would be:
(12+9+27+5-16) / 5 = 47/5 = 9.4%
However annual investment returns are not independent of each other. If there is a major drop in the market one year, there is less capital to invest the next year. The geometric mean will provide a more accurate measurement of the actual average annual return. The geometric mean would be:
(1.12 × 1.09 × 1.27 × 1.05 × 0.84)1/3 = 1.065 = 6.5%
An average of 6.5% per annum increase over five years. Note that 1 is added to each investment return to avoid problems with negative returns. The use of arithmetic mean in a program displaying investment returns will give the wrong impression of actual average returns.
7. Correct
A program which is correct in every way. It is accurate, robust, and is capable of dealing with any input. In reality very few of these programs exist. Here’s one:
int main(void)
{
return 0;
}
[1] Scowen, R.S., Ciechanowicz, Z., “Seven sorts of programs”, SIGPLAN Notices, 17(3), pp.74-79 (1982)