8

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

Tristan
  • 3,845
  • 5
  • 35
  • 58
  • 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 Sep 19 '11 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 Sep 19 '11 at 11:17
  • @cheeken thats a better term then what i used! Significant digit – Tristan Sep 19 '11 at 11:18
  • @cheeken I was wondering because of the pattern of the high margins. There may be some implicit logic. – Bakudan Sep 19 '11 at 11:21

5 Answers5

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/

rabudde
  • 7,498
  • 6
  • 53
  • 91
  • Elegantly simple! My brain wasn't working bad! Just looking at this makes me wonder how i missed this! – Tristan Sep 19 '11 at 12:00
9

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
Alex K.
  • 171,639
  • 30
  • 264
  • 288
2

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));
Nathan Tuggy
  • 2,237
  • 27
  • 30
  • 38
Aaron N
  • 21
  • 1
  • 4
1

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;
}

Jordan Rolph
  • 1,242
  • 1
  • 10
  • 14
1

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

Community
  • 1
  • 1
maialithar
  • 3,065
  • 5
  • 27
  • 44