Numbers - Significant Figures
Numbers can be written to a given number of significant figures by combining the parseFloat() and toPrecision() methods. toPrecision(n) displays a number using n significant digits. However, if the number of significant figures is less than the number of digits before the decimal place, it presents the number in standard index form.
Listing 1
var num = 123456.789;
To show the number to a specified number of significant figures but not in standard index form we can enlist the parseFloat() function. It will show numbers without standard index form when possible.
Listing 2
var num = 123456.789;
However, notice that when the fractional part of the number has trailing zeros parseFloat() removes them. This behaviour is not desired; the zeros are required to show the precision specified. For those numbers parseFloat() is not required as toPrecision() already displayed them correctly.
A Solution: toSignificant()
So, toPrecision() almost gets us there but displays whole numbers in standard index form. We need to use parseFloat() with those whole numbers to display them normally.
If the required number of significant figures is less than the number of digits to the left of the decimal point, toPrecision() will display the number in standard index form. That's when we need to use parseFloat() to display the number normally. We can use logarithms to help us here. The expression Math.log(num) * Math.LOG10E finds the logarithm of num for base 10. It will be one less than the number of digits to the left of the decimal point for numbers with a whole number part (and negative for numbers with no whole number part.
Listing 3
var num = 123456;
function toSigFigs(num, sigFigs) {
num = num.toPrecision(sigFigs);
return sigFigs > Math.log(num) * Math.LOG10E ? num : parseFloat(num);
}
Extending the Number object
We can, if desired, add our function as a method of the Number object, making it available to all numbers.
Listing 4
var num = 0.000123456789;
Number.prototype.toSignificant = function(sigFigs) {
var num = this.toPrecision(sigFigs);
return sigFigs > Math.log(num) * Math.LOG10E ? num : parseFloat(num);
}