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:

bool eq(double a, double b) { return fabs(a - b) <= EPS * max(1.0, max(fabs(a), fabs(b))); }

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:

double sum = 0, c = 0;
for (double x : v) {
    double y = x - c, t = sum + y;
    c = (t - sum) - y;
    sum = t;
}

Pairwise summation — sum recursively in halves; error drops to and it is what std::accumulate on a sorted range effectively achieves. Simply sorting by magnitude before summing captures most of the benefit.

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.

See also: Geometry Basics · Exact Rational Arithmetic · Common Pitfalls