Skip to Content
Course content

10: Floating-Point Types and Precision

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

I want to show you a snippet of code that looks perfectly logical. Imagine you're writing a simple loop to track a progress bar or a timer that increments by 0.1 until it hits 1.0. You'd probably write something like this:

#include <stdio.h>

int main() {
    float progress = 0.0f;
    while (progress != 1.0f) {
        printf("Progress: %f\n", progress);
        progress += 0.1f;
    }
    printf("Reached 1.0!\n");
    return 0;
}

If you run this, you'll notice something unsettling: it never stops. It prints "Progress: 0.900000" and then just keeps sailing right past 1.0, heading toward infinity. You'll be tempted to check your loop logic or your brackets, but the logic is sound. The problem is that the computer is lying to you—or rather, it's doing the best it can with a limited set of tools.

The Binary Fraction Trap

Here is the deal with floating-point numbers: they aren't stored as decimals. They are stored in binary (base-2). In base-10, we can't represent 1/3 exactly (it's 0.333... forever). Similarly, in base-2, a simple number like 0.1 cannot be represented exactly. It becomes a repeating fraction in binary.

When you write 0.1f, the compiler stores the closest possible approximation. Every time you perform progress += 0.1f, you aren't adding exactly one-tenth; you're adding a value slightly off from one-tenth. By the time you get near 1.0, those tiny errors have accumulated. The value of progress might actually be 1.00000012 or 0.9999998. Because it's not exactly 1.00000000, the != operator returns true, and your loop keeps running.

Comparing with an Epsilon

As a rule of thumb: never use == or != with floating-point numbers. Just don't do it. It's a recipe for bugs that are a nightmare to debug because they might work on one compiler but fail on another.

Instead, we use something called an "epsilon." An epsilon is just a fancy name for a very small number that represents the "tolerance" you're willing to accept. Instead of asking "Is this exactly 1.0?", we ask "Is the difference between this value and 1.0 smaller than my tolerance?"

#include <stdio.h>
#include <math.h> // Required for fabsf()

int main() {
    float progress = 0.0f;
    float epsilon = 0.00001f;

    // Check if the absolute difference is greater than our tolerance
    while (fabsf(progress - 1.0f) > epsilon) {
        printf("Progress: %f\n", progress);
        progress += 0.1f;
    }
    printf("Reached (approximately) 1.0!\n");
    return 0;
}

I used fabsf() here, which returns the absolute value of a float. This ensures that whether progress is slightly above or slightly below 1.0, the difference is always positive, and the comparison works.

Float vs. Double: When to Care

You've probably noticed I used float and the f suffix (like 0.1f). In C, a float is typically 32 bits, while a double is 64 bits. A double has much more precision—roughly 15-17 significant decimal digits compared to the 6-9 you get with a float.

In the modern era, memory is cheap. If you aren't working on an embedded microcontroller with a tiny amount of RAM or processing millions of particles in a physics engine, just use double. It reduces the accumulation of rounding errors and saves you from a lot of headaches. If you switch to double, remember to use fabs() instead of fabsf() and drop the f suffixes from your literals.




📋 Practical Task

Build a Precision-Safe Budget Tracker

Create a program that simulates a bank balance. The program should start with a balance of 100.00. Use a loop to subtract a specific "subscription fee" of 0.10 repeatedly until the balance reaches exactly 0.00.

Requirements:

  • Use double for all monetary values to maintain higher precision.
  • Implement the loop termination using an epsilon value (e.g., 0.0001) rather than a direct equality check.
  • Print the balance at every step, formatted to two decimal places using %.2f.
  • Once the loop terminates, print a final message confirming the account is empty.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.