JavaScript “recursion” via setTimeout

I understand that because of JavaScript's single-threaded execution, long loops or recursive calls could make the browser unresponsive while they execute.

I thought about simulating recursion using setTimeout with a delay of 0, so as to queue the next call to execute as soon as possible.

Here's an example comparing a standard recursive factorial function with an attempt to do the same thing but using setTimeout:

function rFactorial(num)
{
if (num === 0) return 1;
else return num * rFactorial( num - 1 );
}

function tFactorial(num, callback, acc) {
acc = acc || 1;
if (num === 0) {
callback(acc);
}
else {
setTimeout(function() {
tFactorial(num-1, callback, acc*num);
}, 0);
}
}


I tested this using the following test:

for (var x = 1; x < 20; x += 1) {
tFactorial(x, (function(n) {
return function(result) {
console.log(rFactorial(n) === result)
};
})(x));
}


This worked for that range of numbers, although for higher numbers the two functions seem to give different results. for example, for 100, sFactorial gives 9.332621544394418e+157, while rFactorial gives 9.33262154439441e+157.

I have two questions:

1. Is this a good approach? Can anyone suggest any improvements etc?
2. Can anyone shed any light on why the two functions give the same results for lower numbers but different results for higher numbers?
-
It may not be directly because of recursion. It may be how you are passing the values per iteration plus the fact that JS is known to mishandle floats. –  Joseph the Dreamer Feb 1 '13 at 15:09
@JosephtheDreamer "JS is known to mishandle floats" ? What does that mean ? –  dystroy Feb 1 '13 at 15:12
You may want to look at this: stackoverflow.com/questions/1458633/… –  Dimitry Feb 1 '13 at 15:15
JS is known to mishandle floats is FUD. Get your facts straight. –  Florian Margaine Feb 1 '13 at 15:31
I was discussing the issue with a clever guy on Stack Overflow, and he found the difference in results is because of differences in the order of multiplication. A simple example: 0.1 * 0.2 * 0.3 yields a different result than 0.3 * 0.2 * 0.1, because intermediate results are different. –  Kendall Frey Feb 1 '13 at 16:30

Using setTimeout or using a recursion might be amusing solutions but they're not terribly efficient (at least until we have tail call optimization in javascript). You'd better use a simple boring loop.
Your computation won't freeze the computer if you try to compute numbers smaller than 2^52 : factorial grows very fast. If you have long computations (which I hadn't thought was the problem), then yes you might use setTimeout or a webworker. –  dystroy Feb 1 '13 at 15:49