Skip to Content
Course content

105: Exponential and Logarithmic Functions

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When you first encounter growth or decay problems in C, your instinct might be to reach for a for loop. If you're calculating compound interest over five years or the population growth of a colony over ten generations, a loop is intuitive. You multiply by a growth factor, store the result, and repeat. It works, and it's easy to debug.

The loop trap and the precision gap

The problem starts when your "time" isn't a whole number. If you need to know the value of an investment at exactly 4.72 years, or the remaining mass of a radioactive isotope after 12.5 days, a loop is useless. You can't iterate "0.72 times."

The naive approach here is often to try and approximate the math using a very small step size in a loop—say, iterating by 0.001 increments. I've seen this in production code before, and it's a nightmare. Not only is it computationally expensive, but you're introducing floating-point accumulation errors at every single step. By the time you reach your target, your answer has drifted because of how double precision works. This is where you stop trying to "simulate" the math and start using the math.h library.

#include <math.h>

// The "simulation" way (Wrong/Naive)
double naive_growth(double initial, double rate, double time) {
    double result = initial;
    for (double t = 0; t < time; t += 0.001) {
        result += result * (rate * 0.001);
    }
    return result;
}

// The professional way
double professional_growth(double initial, double rate, double time) {
    return initial * exp(rate * time);
}

Why pow() isn't always your best friend

Once you move to math.h, the most common mistake I see is the over-reliance on pow(). pow(base, exp) is a Swiss Army knife; it's designed to handle everything from negative bases to fractional exponents. Because it's so general, it's relatively slow.

If you are calculating e raised to a power, never use pow(M_E, x). Use exp(x). It is specifically optimized for the natural base and is significantly faster and more accurate. Similarly, if you just need to square a number, x * x beats pow(x, 2) every single time. I usually tell my juniors: only use pow() when the exponent is a variable that could be anything. If it's a constant or a specific base like e, there's almost always a better tool.

Inverting the growth with logarithms

The real power of this library comes when you need to work backward. Suppose you know the starting amount and the current amount, and you need to find out how much time has passed. In algebra, this is where you'd use a logarithm to "get the variable out of the exponent."

In C, log() is the natural logarithm (base e), not base 10. This trips people up constantly. If your formula requires a common log (base 10), you use log10(). If you're working with the natural growth constant, stick to log().

The trade-off here is mainly about domain errors. Logarithmic functions are only defined for positive numbers. If you pass a zero or a negative number into log(), you'll get a NaN (Not a Number) or a pole error. Unlike a loop that just gives you a weird number, math.h functions will fail loudly if you aren't validating your inputs. Always check that your value is greater than zero before passing it to a log function.




📋 Practical Task

Exercise: Carbon-14 Decay Dating Calculator

You are tasked with writing a program that calculates the age of an organic sample based on its remaining Carbon-14. The formula for the age of a sample is:

t = [ln(N/N0) / -k]

  • t is the age of the sample.
  • N is the remaining amount of C-14.
  • N0 is the initial amount (100%).
  • k is the decay constant for C-14 (approximately 0.00012097 per year).
  • ln is the natural logarithm.

Requirements:

  1. Include <math.h> and link with -lm.
  2. Prompt the user to enter the percentage of Carbon-14 remaining (e.g., 50.0 for 50%).
  3. Validate that the input is between 0 and 100 (exclusive). If the user enters 0 or a negative number, print an error message explaining that logarithms cannot process non-positive values.
  4. Calculate the age of the sample and print it as a double with two decimal places.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.