Skip to the content of the web site.

Step-by-step tracing

IEEE Spectrum Magazine    MIT Technology Review    Wired Magazine    EDN Network    EE Times    Skeptic's Guide to the Universe

Suppose you are attempting to see what your code is doing; that is, you may be asking, how is each instruction affecting the execution of the program?

We will use as an initial example some code that attempts to estimate mortgage payments. Mortgage payments with fixed interest rates are usually straight-forward to calculate:

  • The amount still owed is called the principal.
  • Each month, the interest from that month is calculated and added to the principal.
  • Each month, a payment is made and is thus subtracted from the principal.

Note that there are variable-interest-rate mortgages and mortgages that allow variable payments, but we will ignore those in this example.

Note that "principle" is a noun, while "principal" is an adjective. The "principals" of your elementary and secondary schools were actually the "principal teachers". Similarly, here, the "principal" refers to the "principal amount owed". A good engineer, on the other hand, should live by ethical and professional principles.

You create a project called Mortgage payments and you create a source file mortgage.cpp with the code:

// Library include directives
#include <iostream>

// Function declarations
int main();

// Function definitions
int main() {
        double principal{ 700000.00 };
        double rate{ 0.032 };  // 3.2% per year
        double monthly_payment{ 10000.00 };
        unsigned int num_payments;

        std::cout << "Mortgage amount:  " << principal       << std::endl;
        std::cout << "Mortgage rate:    " << rate            << std::endl;
        std::cout << "Monthly payment:  " << monthly_payment << std::endl;

        for ( num_payments = 0; principal > 0; ++num_payments ) {
                principal *= (1.0 + rate);
                principal -= monthly_payment;
        }

        double final_payment{ monthly_payment + principal };

        std::cout << "Number of months: " << num_payments    << std::endl;
        std::cout << "Final payment:    " << final_payment   << std::endl;

        return 0;
}

You try running this code, but it only prints the first three lines:

Mortgage amount:  700000
Mortgage rate:    0.032
Monthly payment:  10000

Ultimately, you get frustrated, and stop execution by selecting the stop button ().

You'd like to know what's going on. Your first thought might be to log each event. This is not unreasonable, and it seems quite straight-forward, but you must add a lot of code (code that you must remember to delete afterwards).

        for ( num_payments = 0; principal > 0; ++num_payments ) {
		std::cout << (principal*rate) << std::endl;
                principal *= (1.0 + rate);
		std::cout << principal << std::endl;
                principal -= monthly_payment;
		std::cout << principal << std::endl;
		std::cout << (principal/monthly_payment) << std::endl;
        }

You run your code, and you get the rather confusing output

Mortgage amount:  700000
Mortgage rate:    0.032
Monthly payment:  10000
22400
722400
712400
71.24
22796.8
735197
725197
72.5197
23206.3
748403
738403
73.8403
23628.9
762032
752032
75.2032
24065
776097
766097
76.6097
24515.1
790612
780612
78.0612
24979.6
805592
795592
79.5592
25458.9
821051
811051
81.1051

You quickly update your code:

        for ( num_payments = 0; principal > 0; ++num_payments ) {
		std::cout << "Interest owed: " << (principal*rate) << std::endl;
                principal *= (1.0 + rate);
		std::cout << "Principal with interest: " << principal << std::endl;
                principal -= monthly_payment;
		std::cout << "Principal after payment: " << principal << std::endl;
		std::cout << "Finishes: " << (principal/monthly_payment) << std::endl;
		std::cout << std::endl;
        }

Now, the output is slightly more clear:

Mortgage amount:  700000
Mortgage rate:    0.032
Monthly payment:  10000
Interest owed: 22400
Principal with interest: 722400
Principal after payment: 712400
Finishes: 71.24

Interest owed: 22796.8
Principal with interest: 735197
Principal after payment: 725197
Finishes: 72.5197

Interest owed: 23206.3
Principal with interest: 748403
Principal after payment: 738403
Finishes: 73.8403

Interest owed: 23628.9
Principal with interest: 762032
Principal after payment: 752032
Finishes: 75.2032

Interest owed: 24065
Principal with interest: 776097
Principal after payment: 766097
Finishes: 76.6097

Interest owed: 24515.1
Principal with interest: 790612
Principal after payment: 780612
Finishes: 78.0612

Now, very quickly you notice that the principal is increasing each month. Inspecting your code, you determine that the offending statement is the interest calculation:

        for ( num_payments = 0; principal > 0; ++num_payments ) {
		std::cout << "Interest owed: " << (principal*rate) << std::endl;
                principal *= (1.0 + rate);
		std::cout << "Principal with interest: " << principal << std::endl;
                principal -= monthly_payment;
		std::cout << "Principal after payment: " << principal << std::endl;
		std::cout << "Finishes: " << (principal/monthly_payment) << std::endl;
		std::cout << std::endl;
        }

Reviewing the process of mortgage payments, you learn that this should be

        for ( num_payments = 0; principal > 0; ++num_payments ) {
		std::cout << "Interest owed: " << (principal*rate) << std::endl;
                principal *= (1.0 + rate/12.0);
		std::cout << "Principal with interest: " << principal << std::endl;
                principal -= monthly_payment;
		std::cout << "Principal after payment: " << principal << std::endl;
		std::cout << "Finishes: " << (principal/monthly_payment) << std::endl;
		std::cout << std::endl;
        }

You run it again, and after 395 lines of output, you see the answer you were expecting: you clean up your code, deleting the extra cout statements,

        for ( num_payments = 0; principal > 0; ++num_payments ) {
                principal *= (1.0 + rate/12.0);
                principal -= monthly_payment;
        }

and run your code again:

Mortgage amount:  700000
Mortgage rate:    0.032
Monthly payment:  10000
Number of months: 78
Final payment:    5839.28

You see that you would pay off the principal after 78 months, and the last payment would be under $6000.

You can experiment with your code to see that if you double your monthly payment,

Mortgage amount:  700000
Mortgage rate:    0.032
Monthly payment:  20000
Number of months: 37
Final payment:    15836.8

you can pay off the principal 41 months earlier; in three years and one month.

Step-by-step tracing

Now, let's repeat this exercise again, but let us use the IDE to assist us.