I need a function which takes a calculated value (can range from very small to very large) and rounds it to a number of decimal places for display. The number of decimal places should depend on the magnitude of the input and so I can't just use something like .toFixed(n)
because n
is unknown.
I came up with the following, but have the feeling there's a much better way of doing this:
function format_output(output) {
if (output > 10000) {
output = output.toFixed(0);
} else {
if (output > 100 && output < 10000) {
output = output.toFixed(1);
} else {
if (output>1 && output <100) {
output = output.toFixed(3);
} else {
// repeat as necessary
}
return output;
}
Thanks!
I need a function which takes a calculated value (can range from very small to very large) and rounds it to a number of decimal places for display. The number of decimal places should depend on the magnitude of the input and so I can't just use something like .toFixed(n)
because n
is unknown.
I came up with the following, but have the feeling there's a much better way of doing this:
function format_output(output) {
if (output > 10000) {
output = output.toFixed(0);
} else {
if (output > 100 && output < 10000) {
output = output.toFixed(1);
} else {
if (output>1 && output <100) {
output = output.toFixed(3);
} else {
// repeat as necessary
}
return output;
}
Thanks!
Share asked Mar 4, 2013 at 12:37 JamesJames 3116 silver badges17 bronze badges4 Answers
Reset to default 6It does seem that you want to limit this to about five places of precision. This might do so more explicitly:
var toPrecision = function(precision) {
return function(nbr) {
if (typeof nbr !== 'number') return 0; //???
if (nbr === 0) return 0;
var abs = Math.abs(nbr);
var sign = nbr / abs;
nbr = abs;
var digits = Math.ceil(Math.log(nbr)/Math.LN10);
var factor = Math.pow(10, precision - digits);
var result = nbr * factor;
result = Math.round(result, 0);
return result / factor;
};
};
var format_output = toPrecision(5);
format_output(1234567.89012); // 1234600
format_output(987.654321); // 987.65
format_output(-.00246813579); // -0.0024681
Of course you can bine those into a two-argument function if you prefer:
var toPrecision = function(nbr, precision) {
if (typeof nbr !== 'number') return 0; //???
if (nbr === 0) return 0;
var abs = Math.abs(nbr);
var sign = nbr / abs;
nbr = abs;
var digits = Math.ceil(Math.log(nbr)/Math.LN10);
var factor = Math.pow(10, precision - digits);
var result = nbr * factor;
result = Math.round(result, 0);
return result / factor;
};
toPrecision(1234567.89012, 5); // 1234600
Or, if that floats your boat, you could attach it to the Math object:
Math.toPrecision = function(nbr, precision) {
// ...
}
Update (May, 2020)
Many years later, with the ubiquity of ES6, I would write this differently. It might look something like this:
var toPrecision = (precision) => (nbr, _, __, powerOf10) =>
nbr === 0
? 0
: (
powerOf10 = 10 ** (precision - Math .ceil (Math .log10 (Math .abs (nbr)))),
Math .round (nbr * powerOf10) / powerOf10
)
For your requirement you should look into scientific notation
output.toExponential();
If you dont want to use scientific notation try this instead:
function format_output(output) {
var n = Math.log(output) / Math.LN10;
var x = 4-n;
if(x<0)
x=0;
output = output.toFixed(x);
return output;
}
It seems you want to limit the value to 5 significant digits. The following does it for a limited range of values (99999 to 0.00001), you can work out how to do it for the rest. Note that there may be rounding errors in some old browsers for some values.
<input onchange="
var bits = this.value.split('.');
var places = 5 - bits[0].length;
if (places < 0) {
places = 0;
} else if (bits[0] == 0) {
places = 5;
}
this.value = Number(this.value).toFixed(places);
">
This is a method I came up with when trying to solve the same problem, how to dynamically round in order to present both very large and very small numbers to the end user.
function get_exponent_value(num){
value = num.toExponential();
string_e_value = value.split('e')[1];
return parseInt(string_e_value);
}
This gives you the exponent value of a given number. Then, to use it, you round based on this number:
var EValue = get_exponent_value(val);
if (EValue <= -1)
val = float_to_fixed(val, ((EValue * -1) + 3));
else
val = float_to_fixed(val);
This way it gives you reasonable-looking small numbers, and trims decimals from large numbers. It isn't perfect but it works well for now until I can think of / find a better solution.