views:

81

answers:

2

Hi,

I'm trying to write a web app that uses Javascript to perform a fairly complex calculation (involves factorials and Bessel functions). When I run the script in IE, it gives me a warning that the script is unresponsive or taking a long time, and asks if I want to continue running it. I've read that to get around this, you can use either the setTimeout or setInterval commands to essentially reset the counter that IE uses to determine if a script is long-running.

I've tried implementing this, but have not succeeded. When I run a profiler, it appears that my function which computes a factorial is what takes most of the time, so I'd like to use setTimeout in that function. Here's the function I currently have:

function factorial(x) {
    var buff = 1;

    for (i=x;i>=1;i--) {
        buff = buff * i;
    }

    return buff
}

I've tried replacing the code with something like this, but it isn't working properly:

function factorial(x) {
    if (x==0) {
        factbuff=1;
    }
    else {
        factbuff = x;
        factidx = x;
        setTimeout('dofact()',50);
    }
    return factbuff
}

function dofact() {
    if (factidx > 1) {
        factidx--;
        factbuff = factbuff * factidx;
    }
}

Anybody know what I'm doing wrong and how I can correctly implement the setTimeout function in order to calculate a factorial while eliminating the script warning in IE?

+2  A: 
jsumners
I still get the warning prompt that the script is taking a long time to run. If I counted correctly, I have to press no about 13 times before the program actually finishes
Josiah
Does this happen on a specific number? One that I could test for myself? I don't really want to guess at a number that would make IE do its silliness.
jsumners
If you want to see the whole app, you can find it at:ftp://swfscftp.ucsd.edu/users/jrenfree/sphereTS_18Oct2010.htmlI've edited the factorial() code so that if x is greater than 70, then it just sets the result to Infinity. By doing this, I'm still getting accurate results but the script warning only pops up twice in IE before it finishes.Thanks for helping me with this
Josiah
I have replaced my answer with a new function. Give it a try.
jsumners
Ok, now something really weird is going on (well at least to me it's weird). I added the new factorial() function you gave, but sometimes it gives me NaN's and other times it's just fine. If my program has just started and I try factorial(100), then it will work, yet if I try it later on after running factorial a bunch of times, it will result in NaN. Alternatively, if I try factorial(60), one time it will be NaN, then the next is the correct result, then NaN, correct, etc... Why in the world would it be doing this?
Josiah
I added a button to do the calculation 1000 times and append each result to the document body. It executes very quickly on IE8 and does not return 'NaN' for any iteration when calculating 60!. That being said, it wouldn't surprise me if there were a bug in the function.
jsumners
I have updated the test document in my answer with an addition to run the calculation 1000 times. I just tested it in IE6 and IE7 and it runs as expected. If you comment out line 48 (`executions = 0`), then it will fail every other calculation. Also, note that I lowered the setTimeout from 50ms to 1ms in the test document. Doing this still did not result in the warning prompt during my quick tests.
jsumners
Thanks for the code, but something still seems off. In your code, if you try to do 101! or greater, the result is always a NaN. Something screwy must be going on with the setTimeout command so that when executions is greater than 100, it doesn't reset properly. Any ideas why?
Josiah
Yep. I dropped the modulo down to 10 and stepped through it. Once you encounter enough executions to fire the setTimeout, the script keeps calculating the factorial with (likely) the timeout id. Then, after the "answer" has been returned the setTimeout fires and calculates the factorial of NaN. In short, the function is broken. I'm not sure yet what to do to get around this problem.
jsumners
A: 

What if you use memoization techniques to reduce the time consumed by your algorithm?

Check this test: http://jsperf.com/factorial-memoization/20

Matias