最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dynamically round number to n decimal places depending on magnitude - Stack Overflow

programmeradmin1浏览0评论

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 badges
Add a ment  | 

4 Answers 4

Reset to default 6

It 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.

发布评论

评论列表(0)

  1. 暂无评论