将n舍入为m的倍数的有效方法

时间:2011-03-08 08:28:22

标签: optimization math rounding

以下是我目前的情况:

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

一位朋友告诉我,Math.round价格昂贵,更有效的方法是使用模数检查是否必须向上或向下舍入并使用Math.ceilfloor

你会怎么做?

5 个答案:

答案 0 :(得分:3)

为什么不使用模块化运算符和简单的减法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)); 

答案 1 :(得分:1)

伪代码:

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;

答案 2 :(得分:1)

这是一个基于你提到的简单方法:

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

答案 3 :(得分:1)

我认为这正是您所寻找的,但在寻找替代方案之前,您应该验证Math.round的价格是否昂贵。

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

答案 4 :(得分:1)

尝试了很多方法:

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

结果:

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