Number.prototype.toPrecision()
toPrecision(precision) The toPrecision() method returns a string representing the number to the specified precision. Unlike toFixed(), which specifies digits after the decimal point, toPrecision() controls the total number of significant digits — making it ideal for scientific data where precision matters across the entire number.
Syntax
num.toPrecision(precision)
Parameters
| Parameter | Type | Description |
|---|---|---|
precision | number | Number of significant digits (1-21). If omitted, behaves like toString(). |
Return Value
Returns a string (not a number). This is a key distinction from toFixed() and toExponential().
How it differs from toFixed()
The critical difference: toFixed() counts digits after the decimal point, while toPrecision() counts total significant digits across the entire number.
const num = 123.456;
// toFixed() - digits AFTER decimal point
num.toFixed(2); // "123.46"
num.toFixed(4); // "123.4560"
// toPrecision() - TOTAL significant digits
num.toPrecision(4); // "123.5" (4 significant digits)
num.toPrecision(6); // "123.456" (6 significant digits)
Notice how toPrecision(4) produces “123.5” because it rounds to 4 total significant digits, not 4 decimal places. This makes toPrecision() more intuitive for scientific measurements where you care about relative precision, not absolute decimal positions.
Behavior when precision is omitted
When called without arguments, toPrecision() behaves identically to toString() — returning the full number without any rounding:
const num = 123.456;
num.toPrecision(); // "123.456"
num.toString(); // "123.456"
// They return the same result!
This is useful when you want flexible precision — pass a parameter when you need rounding, omit it for full precision.
Scientific data formatting
toPrecision() excels at formatting scientific data because it automatically switches to scientific notation for very large or very small numbers:
// Small numbers - scientific notation kicks in automatically
0.000012345.toPrecision(3); // "1.23e-5"
0.000012345.toPrecision(5); // "1.2345e-5"
// Large numbers
1234567.toPrecision(3); // "1.23e+6"
1234567.toPrecision(6); // "1.235e+6"
This automatic switching makes it perfect for displaying measurements, lab results, and astronomical or atomic-scale values where precision varies across magnitudes.
Examples
The examples below show how toPrecision() behaves across different precision levels and how it compares to toFixed() for the same values. Pay attention to when the output switches to scientific notation — that threshold depends on the number’s magnitude relative to the requested precision.
Basic usage with various precision levels
const num = 5.12345;
num.toPrecision(1); // "5"
num.toPrecision(2); // "5.1"
num.toPrecision(3); // "5.12"
num.toPrecision(5); // "5.1235"
num.toPrecision(8); // "5.1234500"
Comparison with toFixed()
The distinction between toPrecision() and toFixed() becomes clear when you compare their output for the same number. toFixed(2) always shows two decimal places regardless of the integer portion, while toPrecision(4) shows four total digits — if the integer part uses some of those digits, fewer remain for the fractional part. This is why toPrecision(3) on 0.00512 still shows all digits: the leading zeros are not significant.
const value = 99.957;
console.log(value.toFixed(2)); // "99.96" (2 decimal places)
console.log(value.toPrecision(4)); // "99.96" (4 significant digits)
const small = 0.00512;
console.log(small.toFixed(3)); // "0.005" (3 decimal places)
console.log(small.toPrecision(3)); // "0.00512" (3 significant digits!)
Formatting scientific measurements
When displaying scientific constants and measurements, toPrecision() keeps the output compact while preserving meaningful digits. The example below wraps toPrecision() in a helper that detects whether rounding occurred and annotates the output accordingly, so the reader knows when the displayed value is an approximation.
function formatScientific(value, sigFigs = 4) {
const formatted = value.toPrecision(sigFigs);
// Check if the original value was precisely represented
const wasRounded = Number(formatted) !== value;
return wasRounded ? `${formatted} (approx)` : formatted;
}
// Various scientific values
formatScientific(299792458); // "2.998e+8"
formatScientific(6.626e-34); // "6.626e-34"
formatScientific(1.60217663e-19); // "1.602e-19 (approx)"
formatScientific(9.10938e-31); // "9.109e-31 (approx)"
Edge Cases
toPrecision() has well-defined behavior for edge cases that you should understand before using it in production code. Zero always produces a string with the requested number of significant digits after the decimal point. Numbers whose integer part exceeds the requested precision switch to scientific notation. Passing NaN returns the string "NaN", and precision values outside the 1–21 range throw a RangeError.
(0).toPrecision(2); // "0.0"
(100).toPrecision(1); // "1e+2"
(NaN).toPrecision(2); // "NaN"
(1).toPrecision(21); // RangeError: precision must be between 1 and 21
(1).toPrecision(0); // RangeError: precision must be between 1 and 21
When to Use toPrecision()
toPrecision() is the right formatter when you care about the total number of significant digits instead of a fixed number of decimal places. That makes it useful for measurements, scientific data, and values that can vary across several orders of magnitude. The method keeps the output compact while still showing the digits that matter most.
It is easy to confuse with toFixed(), but the intent is different. toFixed() is about display stability, while toPrecision() is about meaningful precision. If the quantity should read like a measurement or report entry, toPrecision() often gives the cleaner result.
Common Mistakes
The biggest surprise is that toPrecision() may switch into scientific notation. That is not a bug. It is the method trying to keep the requested number of significant digits. If you need a fixed decimal presentation for a UI, toFixed() may fit better. If you need a more truthful representation of a very large or very small value, toPrecision() is usually the better match.
Another subtle point is that the output is still a string. Do the math first, then format at the edge where the number is shown or serialized. That keeps arithmetic separate from presentation and avoids double rounding.
See Also
- Number.prototype.toFixed() — Format decimal places
- Number.prototype.toString() — Convert to string