Comparing double values in C
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Comparing double values directly is unreliable in C# because many decimal values cannot be represented exactly in binary floating-point form. The usual fix is not "never compare doubles," but "compare them with a tolerance that matches the scale of the problem."
Why == Often Fails
double follows the IEEE 754 binary floating-point format. That means apparently simple decimal arithmetic can produce tiny representation errors.
The numbers are mathematically equal, but their stored bit patterns differ slightly. Direct equality therefore gives the wrong answer for many real-world calculations.
Use an Absolute Tolerance for Small Values
For values close to zero, an absolute tolerance is often enough.
This says "treat the numbers as equal if the gap is smaller than a fixed threshold." It works well when all expected values live in roughly the same small numeric range.
Use Relative Tolerance for Larger Magnitudes
Absolute tolerance breaks down when numbers become very large. A difference of 0.000001 might be huge in one context and irrelevant in another. Relative tolerance scales the comparison to the magnitude of the values.
This pattern is a better default for general-purpose numeric code because it handles both small and large values more gracefully.
When Exact Equality Is Fine
Not every double comparison needs a tolerance. Exact equality is appropriate when:
- you are comparing against
NaN,Infinity, or-Infinityusing the proper APIs - the values were assigned from the same computation or exact bit-preserving source
- the values represent discrete states encoded as doubles, though that design is uncommon
Examples:
For normal arithmetic results, though, tolerance-based comparison is the safer assumption.
Prefer decimal for Money
Sometimes the correct answer is to stop using double. Financial calculations usually need decimal arithmetic rather than binary floating point.
decimal is slower and has a smaller numeric range than double, but it represents base-10 fractions much more naturally. If the domain is currency, accounting, or invoicing, that tradeoff is usually correct.
A Reusable Helper
For engineering code, it is often worth centralizing the comparison rule:
That avoids inconsistent comparison logic scattered across the codebase.
Common Pitfalls
- Using
==after floating-point arithmetic and expecting mathematically equal values to share identical bit patterns. - Choosing a tolerance by habit instead of from the scale and accuracy requirements of the domain.
- Using only an absolute tolerance when the values can vary across very different magnitudes.
- Forgetting to handle special values such as
NaNand infinity explicitly. - Continuing to use
doublein money-like calculations wheredecimalis the better numeric type.
Summary
- Direct
doubleequality is unreliable after most arithmetic. - Use absolute tolerance for small-scale values and relative tolerance for general cases.
- Pick a tolerance based on the domain, not by guesswork.
- Use
decimalinstead ofdoublefor money-like values. - Handle
NaNand infinity explicitly in reusable comparison helpers.

