2010-07-13 96 views
3
var1=anyInteger 
var2=anyInteger 

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

什麼是上述JavaScript的bitshift替代語法?Javascript bitshift替代math.round

使用整數浮動

謝謝

+0

pn和sn只是整數的變量。(Math.round(2/4)* 4)也可以。 謝謝 – cube 2010-07-12 23:59:30

+0

你確定你的意思是位轉移?位移會使您每次換班時的值增加一倍或一半。如果var2始終是2的冪,那麼它將起作用,但如果var2是一個奇數,處理它的邏輯將比分開它更多的開銷。 – Andir 2010-07-13 02:20:50

+0

讀這幾次,還是不明白你的問題..請改寫你正在嘗試做 – 2010-07-13 02:33:07

回答

7

[增訂] 簡單的回答:

這比在問題中提供的方法Math.round()更快,提供了完全相同的值。

移位比我的測試快10到20%。以下是一些比較兩種方法的更新代碼。

下面的代碼有四個部分:第一,它創建兩組隨機整數10,000組;其次,它在OP的問題中進行一輪,存儲該值供以後比較並記錄執行的總時間;第三,它執行相同的位移,存儲該值供以後比較,並記錄執行時間;第四,它比較圓形和位移值以找出任何差異。它應該報告沒有異常。

請注意,這應該適用於所有正值,非零值。如果代碼遇到分母爲零,它會引發錯誤,我敢肯定負值不會正確位移,儘管我沒有測試過。

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

我不想檢查,但可能保持直接引用'Math.round',說'VAR圓= Math.round;'會給出更準確的結果。 – 2010-07-13 03:41:45

+0

是的。它在Firefox和Chrome上的執行時間減少了約2%。在最新的Safari瀏覽器(速度快5倍)中,差異可以忽略不計。我確實認爲我的位移數學有一個問題。我正在努力改正這一點。 – Andrew 2010-07-13 03:56:47

+2

添加0.5顯然會保留與Math.round()相同的值。更新答案。我測試過的唯一的正整數,我想這不會有任何整數小於1 – Andrew 2010-07-13 04:08:25

-1

不幸的是,比特移位操作通常只與整數工作。你的變量是整數還是浮點數?

+2

JavaScript的數字是64位浮點數。 – 2010-07-12 22:53:34

+0

pn和sn只是整數的變量。 (Math.round(2/4)* 4)也可以。謝謝 – cube 2010-07-13 00:32:47

3

如果VAR2是兩(2^k)的功率可能會 寫

(var1>>k)<<k 

但在一般情況下 沒有簡單的解決辦法。

2

您可以這樣做(var | 0) - 這會將數字截斷爲整數,但您始終可以獲得底價值。如果你想圍繞它,你需要額外的if聲明,但在這種情況下,Math.round反正會更快。

4

你應該能夠通過添加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>