var1=anyInteger
var2=anyInteger
(Math.round(var1/var2)*var2)
What would be the syntax for JavaScripts bitshift alternative for the above?
Using integer not floating
Thank you
var1=anyInteger
var2=anyInteger
(Math.round(var1/var2)*var2)
What would be the syntax for JavaScripts bitshift alternative for the above?
Using integer not floating
Thank you
[UPDATED] The quick answer:
var intResult = ((((var1 / var2) + 0.5) << 1) >> 1) * var2;
It's faster than the Math.round()
method provided in the question and provides the exact same values.
Bit-shifting is between 10 and 20% faster from my tests. Below is some updated code that compares the two methods.
The code below has four parts: first, it creates 10,000 sets of two random integers; second, it does the round in the OP's question, stores the value for later comparison and logs the total time of execution; third, it does an equivalent bit-shift, stored the value for later comparison, and logs the execution time; fourth, it compares the Round and Bit-shift values to find any differences. It should report no anomalies.
Note that this should work for all positive, non-zero values. If the code encounters a zero for the denominator, it will raise and error, and I'm pretty sure that negative values will not bit-shift correctly, though I've not tested.
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;
}
}
you should be able to round any number by adding 0.5 then shifting off the decimals...
var anyNum = 3.14;
var rounded = (anyNum + 0.5) | 0;
so the original expression could be solved using this (instead of the slower Math.round)
((var1/var2 + 0.5)|0) * var2
Run the code snippet below to test different values...
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>
If var2 is a power of two (2^k) you may write
(var1>>k)<<k
but in the general case there is no straightforward solution.
You can do (var | 0)
- that would truncate the number to an integer, but you'll always get the floor value. If you want to round it, you'll need an additional if
statement, but in this case Math.round
would be faster anyway.
Unfortunately, bit shifting operations usually only work with integers. Are your variables integers or floats?