Javascript bitshift替代math.round

时间:2010-07-13 02:15:34

标签: javascript

var1=anyInteger
var2=anyInteger

(Math.round(var1/var2)*var2)

上面的JavaScript bitshift替代方法的语法是什么?

使用不浮动的整数

谢谢

5 个答案:

答案 0 :(得分:8)

[增订] 快速回答:

var intResult = ((((var1 / var2) + 0.5) << 1) >> 1) * var2;

它比问题中提供的Math.round()方法更快,并提供完全相同的值。

比我的测试速度快10到20%。下面是一些比较两种方法的更新代码。

下面的代码有四个部分:首先,它创建了10,000组两个随机整数;第二,它在OP的问题中进行回合,存储该值以供以后比较并记录执行的总时间;第三,它执行等效的位移,存储该值以供以后比较,并记录执行时间;第四,它比较Round和Bit-shift值以找出任何差异。它应该报告没有异常。

请注意,这应适用于所有正,非零值。如果代码遇到分母的零,它会引发错误,我很确定负值不能正确地进行位移,尽管我没有测试过。

var arr1 = [],
    arr2 = [],
    arrFloorValues = [],
    arrShiftValues = [],
    intFloorTime = 0,
    intShiftTime = 0,
    mathround = Math.round, // @trinithis's excellent suggestion
    i;

// Step one: create random values to compare
for (i = 0; i < 100000; i++) {
    arr1.push(Math.round(Math.random() * 1000) + 1);
    arr2.push(Math.round(Math.random() * 1000) + 1);
}

// Step two: test speed of Math.round()
var intStartTime = new Date().getTime();
for (i = 0; i < arr1.length; i++) {
    arrFloorValues.push(mathround(arr1[i] / arr2[i]) * arr2[i]);
}
console.log("Math.floor(): " + (new Date().getTime() - intStartTime));

// Step three: test speed of bit shift
var intStartTime = new Date().getTime();
for (i = 0; i < arr1.length; i++) {
    arrShiftValues.push( ( ( ( (arr1[i] / arr2[i]) + 0.5) << 1 ) >> 1 ) * arr2[i]);

}
console.log("Shifting: " + (new Date().getTime() - intStartTime));

// Step four: confirm that Math.round() and bit-shift produce same values
intMaxAsserts = 100;
for (i = 0; i < arr1.length; i++) {
    if (arrShiftValues[i] !== arrFloorValues[i]) {
        console.log("failed on",arr1[i],arr2[i],arrFloorValues[i],arrShiftValues[i])
        if (intMaxAsserts-- < 0) break;
    }
}

答案 1 :(得分:6)

你应该能够通过加0.5然后移出小数点来舍入任何数字......

var anyNum = 3.14;
var rounded = (anyNum + 0.5) | 0;

因此原始表达式可以使用此解决(而不是较慢的Math.round)

((var1/var2 + 0.5)|0) * var2

运行下面的代码段以测试不同的值...

function updateAnswer() {
  var A = document.getElementById('a').value;
  var B = document.getElementById('b').value;

  var h = "Math.round(A/B) * B = <b>" + (Math.round(A/B) * B) + "</b>";
  h += "<br/>";
  h += "((A/B + 0.5)|0) * B = <b>" + ((A/B + 0.5) | 0) * B +"</b>";
  
  document.getElementById('ans').innerHTML = h;
}
*{font-family:courier}
  A: <input id="a" value="42" />
  <br/>
  B: <input id="b" value="7" />
  <br/><br/>
  <button onclick="updateAnswer()">go</button>
  <hr/>
  <span id="ans"></span>

答案 2 :(得分:3)

如果var2是2(2 ^ k)的幂,你可以  写

(var1>>k)<<k

但在一般情况下  没有直接的解决方案。

答案 3 :(得分:2)

您可以执行(var | 0) - 这会将数字截断为整数,但您始终可以获得最低值。如果您要对其进行舍入,则需要额外的if语句,但在这种情况下,Math.round无论如何都会更快。

答案 4 :(得分:-1)

不幸的是,位移操作通常只适用于整数。你的变量是整数还是浮点数?