为何数学等价的浮点运算表达式会得出不同结果?
First off, your core understanding is spot-on:
- The consistency of outputs d, e, f, g makes perfect sense: all these operations use
floatvariables, so calculations run in single-precision floating-point. The value0.300000011920928955...is the closestfloatrepresentation to the mathematical 0.3, so everyfloat-based operation here converges to that exact value. - The gap between a/b/c and d/e/f/g is indeed driven by compile-time vs runtime evaluation, plus a key C language detail: unadorned floating-point literals like
0.1default todouble(double-precision) type. So a/b/c use higher-precision double calculations, while d/e/f/g use single-precision float.
Now let's break down why a and c match, but b is different:
Key Context: Double-Precision Literals
All literals in a/b/c (0.1, 0.2, 0.3) are stored as double values. Binary floating-point can't represent 0.1, 0.2, or 0.3 exactly—each is stored as the closest possible binary fraction to the decimal value.
Output a: Directly printing 0.3 (double)
The double representation of 0.3 is the closest binary fraction to the mathematical 0.3, which is 0.29999999999999998889776975374843459576368331909180—this is exactly what you see in output a.
Output b: 0.1 + 0.2 (double)
The double versions of 0.1 and 0.2 each carry tiny errors relative to their mathematical values:
0.1as double is0.10000000000000000555111512312578270211815834045410156250.2as double is0.200000000000000011102230246251565404236316680908203125
Adding these two pushes the result to 0.30000000000000004440892098500626161694526672363281—a value slightly larger than the stored double 0.3. The errors from 0.1 and 0.2 add up in a way that lands on a different double value than the literal 0.3.
Output c: (0.1 * 10 + 0.2 * 10) / 10 (double)
This is where compiler optimization takes center stage. Mathematically, this expression simplifies exactly to 0.3. Your compiler performs compile-time constant folding: instead of calculating each step with double precision, it recognizes the mathematical equivalence and replaces the entire expression with the literal 0.3 (as a double). That's why output c matches output a exactly—it's the same underlying double value.
If the compiler didn't perform this optimization, the result might differ slightly, but modern compilers almost always fold this kind of mathematically equivalent constant expression to its simplest form.
内容的提问来源于stack exchange,提问作者anon

