What the types hold

TypeBitsMantissaSignificant decimal digitsMax
float3224~7
double6453~15-16
long double (x86)8064~18-19
__float128128113~33huge

long double is 80-bit on x86 Linux (Codeforces) but the same as double on MSVC — do not rely on it for correctness if the judge’s compiler is unknown.

The rules

Never compare with ==

const double EPS = 1e-9;
bool eq(double a, double b) { return fabs(a - b) < EPS; }
int sgn(double x) { return (x > EPS) - (x < -EPS); }

Choose relative to the magnitude. With values around , a double has absolute precision about , so is smaller than the noise and will misclassify. Use a relative comparison when magnitudes vary (the tested helpers, including a cancellation-free quadratic solver and Kahan summation):

const double EPS = 1e-9;
int sgn(double x) { return (x > EPS) - (x < -EPS); }
bool eqRel(double a, double b) { return fabs(a - b) <= EPS * max(1.0, max(fabs(a), fabs(b))); }
vector<double> quadRoots(double a, double b, double c) {  // a != 0; real roots of ax^2 + bx + c, no cancellation
    double d = b * b - 4 * a * c;
    if (d < 0) return {};
    double q = -0.5 * (b + (b >= 0 ? 1 : -1) * sqrt(d));
    if (q == 0) return {0.0, 0.0};                         // b = 0 and c = 0
    return {q / a, c / q};
}
double kahanSum(const vector<double>& v) {
    double sum = 0, c = 0;
    for (double x : v) { double y = x - c, t = sum + y; c = (t - sum) - y; sum = t; }
    return sum;
}

Where precision is lost

OperationDanger
Subtracting near-equal valuescatastrophic cancellation — the killer
Adding numbers of very different magnitudesthe small one vanishes
Repeated accumulationerror grows as or
sqrt of a tiny negative (from cancellation)NaN
acos of a value slightly outside NaN
Large exponentsoverflow to inf
Comparing computed valuesthe whole problem

The two classic rescues

Quadratic formula. cancels when . Use

Angle between vectors. acos(dot/(|a||b|)) loses precision near and and can feed acos an out-of-range value. Use

double ang = atan2(fabs(cross(a,b)), dot(a,b));

Avoiding floating point entirely

The best fix is not to use it:

Instead ofUse
sqrt(d1) < sqrt(d2)d1 < d2 (squared distances)
a/b < c/da*d < c*b (watch signs and overflow)
Slope comparisoncross product
x == y for rationalsstore pair<num, den> reduced by the gcd
Percentagesscale to integers
Anglescross and dot products
pow(a, b) for integersfast exponentiation with long long
log2(n)__lg(n) or 31 - __builtin_clz(n)

Rule: do every decision in exact arithmetic; use floating point only for the final output.

Summation accuracy

Naive summation of values accumulates error. Two fixes:

Kahan summation: track the lost low-order bits in c (kahanSum above).

Pairwise summation: sum recursively in halves; the error bound drops to . (std::accumulate is plain left-to-right summation, not pairwise.) Sorting by increasing magnitude before a naive sum also helps a lot, because small terms are added to each other before they meet the large ones.

Output

printf("%.10f\n", x);
cout << fixed << setprecision(10) << x << "\n";

Read the statement for the required precision — usually or relative or absolute. Printing more digits than the computation supports is harmless; printing fewer is not.

Watch for negative zero: -0.000000 may be rejected by a strict checker. Add 0.0 or clamp tiny magnitudes to 0 before printing.

Special values

isnan(x)      // NaN != NaN, always
isinf(x)
0.0 / 0.0     // NaN
1.0 / 0.0     // inf

NaN propagates silently through arithmetic and makes every comparison false — which turns a sort with a NaN in the data into undefined behaviour. Guard sqrt and acos arguments.

Compiler flags to avoid

-ffast-math (implied by -Ofast) permits the compiler to reorder floating-point operations and assume no NaN/inf. It can change results and break isnan checks. Do not use it when precision matters.

Related: Big Integers and Fractions, Geometry Primitives.