skip to content

What is the difference between Math and StrictMath, and when would you prefer one over the other?

level: seniorimportance: should knowfreq 35%

answer

  1. Same API, different guarantee: reproducibility vs speed
  2. StrictMath = bit-for-bit identical on every platform (pins fdlibm)
  3. Math = within ~1 ulp, semi-monotonic, may use hardware intrinsics
  4. ulp = unit in the last place (last-bit difference)
  5. Default Math; StrictMath for deterministic sims / distributed agreement

basics

~20 s

StrictMath always gives the exact same bit-for-bit result on every platform. Math may use faster, platform-optimized routines that can differ slightly between machines. Use StrictMath when you need identical results everywhere; otherwise Math is the usual, faster choice.

solid answer

~50 s

Both classes expose the same set of static math functions, but they trade speed against reproducibility. StrictMath guarantees bit-for-bit identical results across every JVM, OS, and CPU — its transcendental functions (sin, cos, log, pow, etc.) are specified to follow the published fdlibm algorithms exactly. Math makes a weaker promise: results must be within a small, documented error bound (often within 1 ulp) and semi-monotonic, but the JVM is free to use intrinsics — hardware instructions or platform libraries — that are faster and can differ in the last bit from one machine to another. In practice many Math methods simply delegate to StrictMath, but you can't rely on that. Prefer Math by default for performance; prefer StrictMath when you need deterministic, portable results — e.g. simulations that must replay identically, distributed computations that compare hashes of floating-point output, or anything where two nodes must agree exactly.

go deeper

for a junior

Knows StrictMath exists and gives the same answer everywhere while Math is the normal, faster default.

for a middle

Can state that StrictMath is bit-for-bit reproducible and Math is allowed to be faster within an error bound, and pick Math by default.

for a senior

Explains ulp/error-bound + semi-monotonic guarantees, that Math may use intrinsics and shouldn't be assumed to equal StrictMath, and names reproducibility use-cases.

for a principal

Decides org-wide when determinism is a correctness requirement (replayable sims, distributed consensus on FP, reproducible builds), and accounts for the strictfp history when reviewing legacy code.

## Two classes, same API Java ships two classes with the *same* set of static math functions: `java.lang.Math` and `java.lang.StrictMath`. `Math.sin`, `Math.pow`, `Math.log` and friends all have an identical counterpart in `StrictMath`. The difference is not *what* they compute but *how precisely and how reproducibly* they compute it. ## Why floating-point results can differ at all Transcendental functions like sine or logarithm cannot be computed exactly with a finite number of operations — they're approximated by algorithms. Different CPUs and math libraries use slightly different approximation routines, so the **last bit** of a `double` result can vary from one machine to another. A `double` has ~15-17 significant decimal digits; the disagreement is typically in that very last digit, but for code that compares results exactly, even one bit matters. The size of such an error is measured in **ulps** — *units in the last place*, i.e. the gap between two adjacent representable `double` values. "Within 1 ulp" means the result is at most one such step away from the true value. ## `StrictMath` — bit-for-bit reproducible `StrictMath` is the **strict** version: its functions are *specified* to produce **exactly the same bits on every platform**, every JVM, every OS, every CPU. To achieve this it pins the algorithms to a well-known reference implementation called **fdlibm** (Freely Distributable Math Library). Run `StrictMath.sin(1.0)` on a laptop, a server, and a phone and you get the identical 64-bit pattern. The cost is that it can't use the fastest hardware path — it must follow the prescribed algorithm. ## `Math` — platform-optimized, within a tolerance `Math` makes a **weaker, performance-oriented** guarantee. The spec says its results must be: - **accurate to within a documented error bound** (for most methods, within 1 ulp, some within 2), and - **semi-monotonic** (if the true function is monotonic over an interval, the approximation doesn't reverse direction). Within those bounds the JVM is free to substitute **intrinsics**: special hardware instructions or optimized native routines that the JIT compiler swaps in for speed. Because that path is platform-dependent, two different machines may return results that differ in the last ulp. Many `Math` methods *delegate to `StrictMath`* in the JDK source today — but that is an implementation detail you must **not** depend on; the contract only promises the error bound. ## How to choose **Default to `Math`.** It's at least as fast and usually faster, and for the vast majority of code a last-bit difference is irrelevant. **Choose `StrictMath` when exact reproducibility is part of correctness:** - **Deterministic simulations / games** that must replay identically from the same seed across machines. - **Distributed systems** where nodes compute floating-point values and then compare or hash them — any disagreement breaks consensus. - **Cross-platform test oracles** that assert exact expected `double` outputs. - **Regulatory or scientific** computations requiring documented, portable results. ## Historical note: `strictfp` There used to be a related keyword, `strictfp`, that forced strict IEEE-754 intermediate evaluation on expressions. As of Java 17 all floating-point arithmetic is strict by default and `strictfp` is effectively a no-op, but the `Math` vs `StrictMath` distinction for the *library functions* still stands and is the relevant one today. ## One-line summary Same functions; `StrictMath` = identical bits everywhere (reproducible, possibly slower), `Math` = within a small error bound and free to be faster (possibly differs by an ulp between platforms).

  • Does Math always delegate to StrictMath?
    Often it does in the current JDK, but you must not rely on it. The Math contract only promises results within a small error bound; the JVM may swap in platform intrinsics, so behavior can differ by an ulp and is not guaranteed to match StrictMath.
  • What is an 'ulp'?
    Unit in the last place — the distance between a floating-point value and the next representable one. It's the natural unit for expressing floating-point error; 'within 1 ulp' means at most one representable step from the true value.

saying these in an interview costs you the question

  • Claiming Math and StrictMath always return identical results (only StrictMath guarantees that).
  • Saying StrictMath is more 'accurate' — it's more reproducible; both are close to the true value, Math may even be just as accurate.
  • Assuming Math is slower because it's 'less strict' — Math is the faster/default one.
  • Confusing the strictfp keyword (now a no-op) with the Math/StrictMath library distinction.

context