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

math - Javascript intelligent rounding - Stack Overflow

programmeradmin2浏览0评论

I currently need to round numbers up to their nearest major number. (Not sure what the right term is here)

But see an example of what I'm trying to achieve

IE:

 13 // 20
 349 // 400
 5645 // 6000
 9892 // 10000
 13988 // 20000
 93456 // 100000
 231516 // 300000

etc. etc.

I have implemented a way of doing this but its so painful and only handles numbers up to a million and if I want it to go higher I need to add more if statements (yeah see how i implmented it :P im not very proud, but brain is stuck)

There must be something out there already but google is not helping me very much probably due to me not knowing the correct term for the kind of rounding i want to do

I currently need to round numbers up to their nearest major number. (Not sure what the right term is here)

But see an example of what I'm trying to achieve

IE:

 13 // 20
 349 // 400
 5645 // 6000
 9892 // 10000
 13988 // 20000
 93456 // 100000
 231516 // 300000

etc. etc.

I have implemented a way of doing this but its so painful and only handles numbers up to a million and if I want it to go higher I need to add more if statements (yeah see how i implmented it :P im not very proud, but brain is stuck)

There must be something out there already but google is not helping me very much probably due to me not knowing the correct term for the kind of rounding i want to do

Share Improve this question asked Sep 19, 2011 at 11:08 TristanTristan 3,8855 gold badges36 silver badges58 bronze badges 4
  • And I need a girlfriend, but we may have to work to get the things done! What is the logic to have 349->400 instead of 500, 13988->20000, instead of 15000, 231516->300000 instead of 250000?!? – Bakudan Commented Sep 19, 2011 at 11:11
  • 1 @Bakudan There is a logic to the examples Tristan has posted. Essentially, you simplify the number to 1 significant digit, always rounding up. – cheeken Commented Sep 19, 2011 at 11:17
  • @cheeken thats a better term then what i used! Significant digit – Tristan Commented Sep 19, 2011 at 11:18
  • @cheeken I was wondering because of the pattern of the high margins. There may be some implicit logic. – Bakudan Commented Sep 19, 2011 at 11:21
Add a comment  | 

5 Answers 5

Reset to default 15
<script type="text/javascript">
    function intelliRound(num) {
        var len=(num+'').length;
        var fac=Math.pow(10,len-1);
        return Math.ceil(num/fac)*fac;
    }
    alert(intelliRound(13));
    alert(intelliRound(349));
    alert(intelliRound(5645));
    // ...
</script>

See http://jsfiddle.net/fCLjp/

One way;

var a = [13, // 20
 349, // 400
 5645, // 6000
 9892, // 10000
 13988, // 20000
 93456, // 100000
 231516 // 300000
]

for (var i in a) {
    var num = a[i];
    var scale = Math.pow(10, Math.floor(Math.log(num) / Math.LN10));
    print([ num, Math.ceil(num / scale) * scale ])
}

13,20
349,400
5645,6000
9892,10000
13988,20000
93456,100000
231516,300000

The answer from @rabudde works well, but for those that need to handle negative numbers, here's an updated version:

function intelliRound(num) {
     var len = (num + '').length;
     var result = 0;
     if (num < 0) {
         var fac = Math.pow(10, len - 2); 
         result = Math.floor(num / fac) * fac;
     }
     else {
        var fac = Math.pow(10, len - 1);
        result = Math.ceil(num / fac) * fac;
     }
     return result;
}
alert(intelliRound(13));
alert(intelliRound(349));
alert(intelliRound(5645));
            
alert(intelliRound(-13));
alert(intelliRound(-349));
alert(intelliRound(-5645));

you can use Math.ceil function, as described here:

javascript - ceiling of a dollar amount

to get your numbers right you'll have to divide them by 10 (if they have 2 digits), 100 (if they have 3 digits), and so on...

The intelliRound function from the other answers works well, but break with negative numbers. Here I have extended these solutions to support decimals (e.g. 0.123, -0.987) and non-numbers:

/**
 * Function that returns the floor/ceil of a number, to an appropriate magnitude
 * @param {number} num - the number you want to round
 *
 * e.g.
 * magnitudeRound(0.13) => 1
 * magnitudeRound(13) => 20
 * magnitudeRound(349) => 400
 * magnitudeRound(9645) => 10000
 * magnitudeRound(-3645) => -4000
 * magnitudeRound(-149) => -200
 */

function magnitudeRound(num) {
  const isValidNumber = typeof num === 'number' && !Number.isNaN(num);
  const result = 0;

  if (!isValidNumber || num === 0) return result;
  const abs = Math.abs(num);
  const sign = Math.sign(num);

  if (abs > 0 && abs <= 1) return 1 * sign; // percentages on a scale -1 to 1
  if (abs > 1 && abs <= 10) return 10 * sign;
  const zeroes = `${Math.round(abs)}`.length - 1; // e.g 123 => 2, 4567 => 3
  const exponent = 10 ** zeroes; // math floor and ceil only work on integer
  const roundingDirection = sign < 0 ? 'floor' : 'ceil';

  return Math[roundingDirection](num / exponent) * exponent;
}

发布评论

评论列表(0)

  1. 暂无评论