An efficient way to round n to a multiple of m

Here I have:

function getNearestMultipleOf(n, m) {
    return Math.round(n/m) * m;
}
console.log(getNearestMultipleOf(37,18)); //36

A friend told me that Math.round is expensive and a more efficient way is to use modulo to check if n needs to be rounded up or down and use either Math.ceil, or floor.

How do you do this?

+3
source share
5 answers

I tried several ways:

<script>

// Math
var floor = Math.floor;
var time1 = +new Date();
var n = 586;
var m = 18;

// Math.round
for (var h=1.01, i = 5000000; i--;) {
   Math.round(n/m) * m;
}
console.log("Math.round:" + (+new Date() - time1));

// Math.ceil/floor
time1 = +new Date();
for (var h=1.01, i = 5000000; i--;) {
   if (n%m < m/2) {
        Math.floor(n/m) * m;
    } else {
        Math.ceil(n/m) * m;
    }
}
console.log("Math.floor/ceil:" + (+new Date() - time1));

// Shorter Math.ceil/floor
time1 = +new Date();
for (var h=1.01, i = 5000000; i--;) {
    Math[n%m < m/2 ? 'floor' : 'ceil'](n/m) * m;
}
console.log("Shorter Math.ceil/floor:" + (+new Date() - time1));

// Bitwise1
time1 = +new Date();
for (var h=1.01, i = 5000000; i--;) {
   if (n%m < m/2) {
        ~~(n/m) * m;
    } else {
        ~~(n/m + 1) * m;
    }
}
console.log("Bitwise1:" + (+new Date() - time1));

// Bitwise2
time1 = +new Date();
for (var h=1.01, i = 5000000; i--;) {
   ~~(n/m + 0.5) * m;
}
console.log("Bitwise2:" + (+new Date() - time1));

// lessOne/moreOne
time1 = +new Date();
for (var h=1.01, i = 5000000; i--;) {
    lessOne = n-(n%m);
    moreOne = lessOne + m;
    if((n-lessOne) < (moreOne - n)) {
        //lessOne;
    } else {
        //moreOne;
    }
}
console.log("lessOne/moreOne:" + (+new Date() - time1));

</script>

Result:

Math.round:188
Math.floor/ceil:215
Shorter Math.ceil/floor:381
Bitwise1:171
Bitwise2:135
lessOne/moreOne:120
+1
source

Why not use a modular operator and simple dressing ? http://jsfiddle.net/LCDy6/1/

function getNearestMultipleOf(n, m) {
    lessOne = n-(n%m);
    moreOne = lessOne + m;
   if((n-lessOne) < (moreOne - n))
        return lessOne;
    else
        return moreOne;   
}
alert(getNearestMultipleOf(38,3)); 
+3
source

:

let r = n modulo m;
let q = Math.Floor( n / m );  //div
if(r < m / 2.0) 
   answer = q*m;
else
   answer = (q+1)*m;
+1

, , :

function getNearestMultipleOf(n, m) {
    if (n % m >= m / 2) {
        return Math.ceil(n/m) * m;
    }
    else {
        return Math.floor(n/m) * m;
    }
}
+1

I think this is what you are looking for, but you should probably check the statement that Math.round is expensive before looking for an alternative.

function getNearestMultipleOf(n,m) { 
    return Math[n%m < m/2 ? 'floor' : 'ceil'](n/m) * m;
}
+1
source

All Articles