Explained clearly 5 min read

Significant Figures in JavaScript: Avoiding Floating-Point Rounding Errors

JavaScript numbers are IEEE 754 binary64, so decimal significant-figure rounding can produce surprising results. This reference explains the rules, standards, and safe patterns.

Short Answer

JavaScript numbers are IEEE 754 binary64, so decimal significant-figure rounding can produce surprising results. This reference explains the rules, standards, and safe patterns.

Rule Statement

Significant figures are the digits in a measured value that carry meaning for its precision. In JavaScript, every Number is an IEEE 754 binary64 floating-point value, so decimal significant-figure rounding can produce surprising results. The governing rule is simple: determine significant figures from the measurement, carry extra digits through intermediate calculations, and round only once at the final step. This site is a precision and rounding reference, not merely a calculator; the significant figures calculator implements the same decimal-safe rules documented here.

  • All non-zero digits are significant.
  • Zeros between non-zero digits are significant.
  • Leading zeros are never significant.
  • Trailing zeros after a decimal point are significant.
  • Trailing zeros in a whole number without a decimal point are ambiguous; use scientific notation or an overline to remove ambiguity.

For addition and subtraction, round to the least precise decimal place. For multiplication and division, round to the least number of significant figures. See addition and subtraction rules and multiplication and division rules.

Standards Citation

Metrology and testing standards give authoritative rounding guidance. ISO 80000-1:2009, Quantities and units — Part 1: General, Clause 7.3.4 requires that rounding be performed in one step to avoid double-rounding error. ASTM E29-13a, Standard Practice for Using Significant Digits in Test Data to Determine Conformance with Specifications, Section 6 specifies rounding rules, including round half even for exact ties. JCGM 100:2008 (the GUM), Clause 7.2.2 recommends that uncertainty be reported to two significant digits. NIST Technical Note 1297, Section 7.2, gives compatible guidance for expressing uncertainty.

Round once, at the end. Report uncertainty and value with consistent significant digits. Do not let binary floating-point artifacts dictate decimal precision.

Software Behavior Note: JavaScript and IEEE 754

ECMAScript uses IEEE 754 binary64 for all Number values. There is no native decimal type. Values such as 0.1, 0.2, and 1.005 are not exactly representable in binary, so they are stored as nearby binary fractions. The classic demonstration is:

0.1 + 0.2 // 0.30000000000000004

Number.prototype.toFixed and Number.prototype.toPrecision return strings, but they operate on the underlying binary value. That means tie cases can round in unexpected directions. For example, (1.005).toFixed(2) returns '1.00', not '1.01', because 1.005 is stored slightly below 1.005. Math.round rounds half toward positive infinity: Math.round(2.5) is 3, but Math.round(-2.5) is -2. It is not banker’s rounding and does not follow ASTM E29 tie rules.

For significant-figure work, parse decimal input as a string, round on decimal digits, or use a decimal library such as decimal.js or big.js. If you must use native methods, treat them as display helpers, not as metrology-grade rounding engines.

Worked Examples

Example 1: 1.005 to three significant figures

Exact decimal reasoning: the digits are 1, 0, 0, and the next digit is 5. Round half up gives 1.01. In JavaScript, (1.005).toPrecision(3) returns '1.00' because the stored value is approximately 1.00499999999999989. The safe pattern is to parse the string '1.005' and round in decimal space.

Example 2: 0.1 + 0.2

The exact decimal sum is 0.3. JavaScript returns 0.30000000000000004. If the final answer is limited to one significant figure, report 0.3. The artifact is invisible after rounding, but it can break equality tests and accumulate in long calculations.

Example 3: 123.456 to four significant figures

Exact decimal: 123.5. JavaScript: (123.456).toPrecision(4) returns '123.5'. This case works because the binary error is far below the rounding threshold. Do not generalize from a single success.

Example 4: Multiplication with significant figures

Multiply 2.34 by 5.6. The exact product is 13.104. The first factor has three significant figures; the second has two. The result must have two significant figures: 13. JavaScript may show 13.104000000000001, so round only after the multiplication.

Counter-Examples

  • Counter-example 1: (1.005).toFixed(2) gives '1.00'. Expected decimal result: '1.01'.
  • Counter-example 2: Math.round(-2.5) gives -2. A symmetric half-away-from-zero rule would give -3.
  • Counter-example 3: Rounding after every step. Adding 0.1, 0.2, and 0.3 and rounding to one significant figure at each stage can hide the true final precision. Round once at the end.
  • Counter-example 4: Assuming 1.230 stores four significant figures. JavaScript stores the same Number for 1.230 and 1.23; trailing zeros are not preserved.

Convention Comparison Table

Convention Rule JavaScript behavior Typical use
Round half up Exact 5 rounds away from zero Math.round rounds half toward +Infinity School arithmetic
Round half even Exact 5 rounds to nearest even digit Not native for Math.round ASTM E29, banking, metrology
Truncation Discard extra digits Math.trunc Not recommended for measurement
Decimal string rounding Operate on decimal digits Custom code or decimal library Significant figures, money

Common Mistakes

  • Confusing decimal places with significant figures.
  • Using binary floats for decimal money or exact decimal measurements.
  • Double rounding: rounding intermediate results before the final step.
  • Treating exact numbers, such as counts or defined constants, as if they limited significant figures.
  • Assuming toPrecision always produces standards-compliant significant-figure rounding.
  • Ignoring uncertainty propagation. See error propagation and measurement uncertainty.

Quick Reference Table

Task JavaScript method Notes
Round to decimal places Number.prototype.toFixed(f) Returns string; binary tie issues; half away from zero in spec.
Round to significant figures Number.prototype.toPrecision(p) Returns string; p is total digits; binary representation can affect ties.
Round to integer Math.round(x) Half toward +Infinity; not banker’s rounding.
Exact decimal arithmetic decimal.js, big.js, BigInt scaling Recommended for sig-fig critical work.

Sources & Further Reading

  • ISO 80000-1:2009, Quantities and units — Part 1: General, Clause 7.3.4.
  • ASTM E29-13a, Standard Practice for Using Significant Digits in Test Data to Determine Conformance with Specifications, Section 6.
  • JCGM 100:2008, Evaluation of measurement data — Guide to the expression of uncertainty in measurement (GUM), Clause 7.2.2.
  • NIST Technical Note 1297, Guidelines for Evaluating and Expressing the Uncertainty of NIST Measurement Results, Section 7.2.
  • ECMAScript Language Specification, Number.prototype.toFixed and Number.prototype.toPrecision.
  • IEEE 754-2019, Standard for Floating-Point Arithmetic.

FAQ

Why does 0.1 + 0.2 not equal 0.3 in JavaScript?

Because 0.1 and 0.2 are not exactly representable in IEEE 754 binary64. The sum is 0.30000000000000004. This is a floating-point representation artifact, not a JavaScript bug.

How do I round to significant figures in JavaScript?

For exact decimal inputs, parse as a string and round on decimal digits, or use a decimal library. For display, toPrecision can work, but test tie cases and trailing zeros. The site calculator performs decimal-safe significant-figure rounding.

Is Math.round the same as ASTM E29 rounding?

No. Math.round rounds half toward +Infinity. ASTM E29-13a and many metrology guides use round half even for exact ties. Use a decimal library for standards-compliant rounding.

Does toPrecision preserve trailing zeros?

It returns a string with the requested precision, so it can display trailing zeros. The underlying Number does not store them. 1.230 and 1.23 are the same Number value.

Verified sources

References

  1. ISO 80000-1:2009, Quantities and units — Part 1: General, Clause 7.3.4.
  2. ASTM E29-13a, Standard Practice for Using Significant Digits in Test Data to Determine Conformance with Specifications, Section 6.
  3. JCGM 100:2008, Evaluation of measurement data — Guide to the expression of uncertainty in measurement (GUM), Clause 7.2.2.
  4. NIST Technical Note 1297, Guidelines for Evaluating and Expressing the Uncertainty of NIST Measurement Results, Section 7.2.
  5. ECMAScript Language Specification, Number.prototype.toFixed and Number.prototype.toPrecision.
  6. IEEE 754-2019, Standard for Floating-Point Arithmetic.

Leave a Reply

Your email address will not be published. Required fields are marked *