C programming
floating point precision
numerical computation
software development
programming bugs

Problem with Precision floating point operation in C

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Floating-point precision surprises in C are usually expected behavior, not random arithmetic failures. Decimal values like 0.1 often cannot be represented exactly in binary floating formats, so tiny rounding differences appear in results. Correct C code handles this with tolerant comparisons, numerically stable algorithms, and appropriate type choice for domain requirements.

Why Exact Decimal Equality Often Fails

Most C platforms implement IEEE 754 float and double. These types store the nearest representable binary value, not exact decimal fractions.

c
1#include <stdio.h>
2
3int main(void) {
4    double a = 0.1;
5    double b = 0.2;
6    double c = a + b;
7
8    printf("a = %.17f\n", a);
9    printf("b = %.17f\n", b);
10    printf("c = %.17f\n", c);
11    printf("c == 0.3 ? %s\n", (c == 0.3) ? "true" : "false");
12
13    return 0;
14}

The comparison often prints false because exact equality is too strict for rounded values.

Use Tolerance-Based Comparison

For computed values, compare with absolute and relative tolerances.

c
1#include <math.h>
2
3int almost_equal(double x, double y, double abs_eps, double rel_eps) {
4    double diff = fabs(x - y);
5    if (diff <= abs_eps) {
6        return 1;
7    }
8
9    double scale = fmax(fabs(x), fabs(y));
10    return diff <= rel_eps * scale;
11}

Example usage:

c
1#include <stdio.h>
2
3int main(void) {
4    double x = 0.1 + 0.2;
5    double y = 0.3;
6
7    if (almost_equal(x, y, 1e-12, 1e-12)) {
8        puts("close enough");
9    } else {
10        puts("different");
11    }
12
13    return 0;
14}

Tolerance values should match your domain, not a random constant copied from another project.

Accumulation Error and Stable Summation

Adding many values can amplify rounding error, especially when values differ greatly in magnitude.

c
1#include <stdio.h>
2
3double kahan_sum(const double *arr, int n) {
4    double sum = 0.0;
5    double comp = 0.0;
6
7    for (int i = 0; i < n; ++i) {
8        double y = arr[i] - comp;
9        double t = sum + y;
10        comp = (t - sum) - y;
11        sum = t;
12    }
13
14    return sum;
15}
16
17int main(void) {
18    double values[] = {100000000.0, 1.0, -100000000.0};
19    int n = (int)(sizeof(values) / sizeof(values[0]));
20
21    double naive = values[0] + values[1] + values[2];
22    double improved = kahan_sum(values, n);
23
24    printf("naive = %.1f\n", naive);
25    printf("kahan = %.1f\n", improved);
26    return 0;
27}

Stable algorithms such as Kahan summation can preserve small contributions lost by naive accumulation.

Choose Numeric Type by Data Semantics

Use double for most scientific and engineering calculations unless memory constraints require float. For exact decimal domains like money, prefer scaled integers.

c
1#include <stdio.h>
2
3int main(void) {
4    long long subtotal_cents = 1099;
5    long long tax_cents = 88;
6    long long total_cents = subtotal_cents + tax_cents;
7
8    printf("total = %lld.%02lld\n",
9           total_cents / 100,
10           total_cents % 100);
11
12    return 0;
13}

This avoids floating drift for financial totals and comparisons.

Platform and Compiler Effects

Floating-point results can differ slightly across compilers, instruction sets, and optimization levels. For portable behavior:

  • Keep compiler flags consistent in CI and production.
  • Use tolerance-based assertions in tests.
  • Avoid depending on one exact least-significant-bit output.

Numerical code should be designed for stability across valid platform implementations.

Debugging Workflow for Precision Issues

When debugging numeric discrepancies:

  1. Print intermediate values at high precision.
  2. Isolate the first step where results diverge.
  3. Compare naive and stable algorithm variants.
  4. Test large magnitudes, tiny increments, and cancellation-heavy expressions.

This process identifies root cause much faster than changing random constants.

Common Pitfalls

  • Comparing computed floating-point values with strict ==.
  • Using one global epsilon for all modules and scales.
  • Mixing float and double unintentionally in expressions.
  • Summing values in numerically unstable order.
  • Using floating-point arithmetic where exact decimal semantics are required.

Summary

  • Floating-point approximation is expected in C due to binary representation.
  • Exact decimal equality after arithmetic is often the wrong validation method.
  • Use absolute plus relative tolerance for robust comparisons.
  • Stable summation algorithms reduce accumulation error.
  • For exact-money style domains, use scaled integers instead of floats.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.