Max call stack exceeded - javascript

I understand what maximum call stack exceeded is. However, is there a workaround for this for my code? Furthermore, there will be a time where it eventually will stop looping, that is when position > counter1.
var a = 0;
var b = 1;
var c;
var counter1 = 1;
var position = 0;
window.onload = function() {
var position = prompt("Please enter the position number.","0");
calc1();
}
function calc1() {
if(position <= counter1) {
c = a+b;
counter1++;
calc2();
}
else {
callResult();
}
}
function calc2() {
if(position <= counter1) {
a = b+c;
counter1++;
calc3();
}
else {
callResult();
}
}
function calc3() {
if(position <= counter1) {
b = c+a;
counter1++;
calc1();
}
else {
callResult();
}
}
function callResult() {
if (position %3 == 1) {
document.getElementById("answer").innerHTML = a;
}
else if (position %3 == 2) {
document.getElementById("answer").innerHTML = b;
}
else {
document.getElementById("answer").innerHTML = c;
}
}

You should avoid recursion and use loop. Something like this:
window.onload = function() {
var position = prompt("Please enter the position number.","0");
maincalc();
}
function maincalc() {
var subcalc = [ calc1, calc2, calc3 ];
var calccount = 0;
while(position <= counter1) {
subcalc[ calccounter ]();
calccounter = (calccounter +1) % 3;
}
}

The value of position is given once and never changed.
You then check, if(position <= counter1) in each call calc1, calc2, calc3 which call each other thus:
calc1 -> calc2 -> calc3 -> calc1 -> ...
This will clearly continue until you run out of stack space.
Perhaps if you increment position instead of counter1 or keep calling while position is greater than the counter this problem will go away,
i.e.
if(position > counter1)
You probably need to step back and think about what you are really trying to do.

as I understand you are calculating Fibonacci numbers sum?
see this Javascript Fibonacci answer to learn how to do it much easier and without any recursive calls

Related

for loop in javascript is skipping else if condition half the time

I'm was just fiddling around with javascript and I wrote function using Math.random that I thought would return a coin-flip. Then I was curious so I ran it through a loop to test how often it flips true/false. I found out my loop is skipping about half of the else if conditions, and was able to verify this by catching them in the errors var. So, why is it doing this?
var truths = 0;
var alternativetruths = 0;
var errors = 0;
function game() {
var score = Math.random()*10;
return score>5;
}
for(i=0;i<999999;i++) {
if (game() === true) {
truths++
} else if (game() === false) {
alternativetruths++
} else {
errors++
}
}
console.log("truths:",truths,"alternativetruths:",alternativetruths,"errors:",errors)
truths: 500393 alternativetruths: 249580 errors: 250026
Your code calls game() twice. If the first call isn't true, then the second might or might not be true.
Just call game() once and assign the result to a variable. Don't make explicit comparisons to true and false; if statements work off boolean values, and your function already returns one of those.
for (var i = 0; i < 999999; i++) {
var result = game();
if (result)
truths++;
else
alternativetruths++;
}
Because you're calling game twice, and thus getting two different random flags.
The minimal change is to remember the number:
for(i=0;i<999999;i++) {
var flag = game();
if (flag === true) {
truths++
} else if (flag === false) {
alternativetruths++
} else {
errors++
}
}
But a couple of other notes:
If flag is a boolean (and it is, it's the result of the > operator), then if (flag === true) is pointless. Just use if (flag). The result of the === operator is a boolean too, so if you don't trust them to be true or false, where do you stop? :-) if ((flag === true) === true)?
Separately, if (flag === false) should just be if (!flag).
If flag is a boolean (and it is), then if you have if (flag), having else if (!flag) and then else doesn't make any sense. There is no way you'll reach that final else. Just if (flag) { } else { } is all you need.
But, game isn't fair, it has a very slight bias toward returning false. Remember, the range returned by Math.random() * 10 is 0 to just under 10, so checking for > 5 means you're skipping the midpoint. Because you're dealing with very small fractional numbers, you don't notice the bias, but it's there; it would be more obvious if you rounded to whole numbers, at which point it would be roughly 40%/60% true/false. You want >= 5 for fair results.
game can rather moer succinctly be written: return Math.random() >= 0.5;.
Because you're not declaring i, you're falling prey to The Horror of Implicit Globals (that's a post on my anemic little blog). Remember to declare your variables.
Re > vs. >=, here's an example where I've rounded to whole numbers to make the effect clearer:
for (var n = 0; n < 4; ++n) {
setTimeout(test.bind(null, n, true), 200 * n);
setTimeout(test.bind(null, n, false), 200 * n + 100);
}
function test(num, gte) {
var truths = 0;
var alternativetruths = 0;
var errors = 0;
function game() {
var score = Math.floor(Math.random() * 10);
return gte ? score >= 5 : score > 5;
}
for (var i = 0; i < 999999; i++) {
var flag = game();
if (flag) {
truths++;
} else {
alternativetruths++;
}
}
showStats(num, gte, truths, alternativetruths);
}
function showStats(num, gte, truths, alternativetruths) {
var total = truths + alternativetruths; // Should be 999999 of course
var truthsPercent = (truths * 100) / total;
var altPercent = (alternativetruths * 100) / total;
console.log(num, gte ? ">=" : ">", "truths:", truths, "alternativetruths:", alternativetruths, "(" + truthsPercent.toFixed(2) + "% vs. " + altPercent.toFixed(2) + "%)");
}
.as-console-wrapper {
max-height: 100% !important;
}
You need to assign game to a var before test for its value. Otherwise, everytime yout check the value with game() you will check a new value. So it can be false at the first check and true at the second and for this reason increment your errors.
Try this:
for(i=0;i<999999;i++) {
let gameResult = game();
if (gameResult === true) {
truths++
} else if (gameResult === false) {
alternativetruths++
} else {
errors++
}
}

What will run faster?

I made this thumbnail rotator in javascript, and figured it could be written shorter as seen in the first example, however will this help performance? and are there any general guidelines you should follow in order to maximize javascript speed? (pardon my ugly code, I'm very new to the game)
function mouseOverfirst(videoId){
var num = 8;
var numb = 7;
$('#'+videoId).attr('src',videoId+'/thumb'+numb+'.png');
if(numb == 7){
interval = setInterval(function(){
$('#'+videoId).attr('src',videoId+'/thumb'+num+'.png');
if(num == 15){
num = 1;
}
else
{
num++;
}
},500);
}
}
or this?
function mouseOverfirst(videoId){
var numb = 7;
$('#'+videoId).attr('src',videoId+'/thumb'+numb+'.png');
if(numb == 7){
mouseOver('video1');
}
}
function mouseOver(videoId){
var num = 8;
interval = setInterval(function(){
$('#'+videoId).attr('src',videoId+'/thumb'+num+'.png');
if(num == 15){
num = 1;
}
else
{
num++;
}
},500);
}
The complexity of both programs are the same.
It doesn't matter which one you use, but the 2nd one is more approachable as a function mouseOverFirst and mouseOver can be reused easily.

javascript recursion counter

I tried to rewrite this indexOf MDN example to practice recursion
var str = 'To be, or not to be, that is the question.';
var count = 0;
var pos = str.indexOf('e');
while (pos !== -1) {
count++;
pos = str.indexOf('e', pos + 1);
}
console.log(count); // displays 4
This was my solution:
var count = 0;
function countLetters(str, p) {
var pos = str.indexOf(p);
if (pos == -1) {
return count;
}
else {
count ++;
return countLetters(str.substr(pos + 1), p)
}
}
console.log(countLetters('To be, or not to be, that is the question.', 'e'));
It works, but is there anyway to get the count variable inside the function itself? Is it not really a true recursion if I have a count variable outside the function?
In a recursive function, if you want to keep a variable around from one "iteration" to the next, then you need to pass it as an argument:
function countLetters(str, p, count) {
count = count || 0;
var pos = str.indexOf(p);
if (pos == -1) {
return count;
}
else {
return countLetters(str.substr(pos + 1), p, count + 1);
}
}
console.log(countLetters('To be, or not to be, that is the question.', 'e'));
// => 4
However, this is not always necessary, as Arun P Johny's answer illustrates.
What you can do is to return the count value form the method, so if the item is not found you return 0, else you return 1 + value-of-recursive-call
function countLetters(str, p) {
var pos = str.indexOf(p);
if (pos == -1) {
return 0;
} else {
return 1 + countLetters(str.substr(pos + 1), p)
}
}
console.log(countLetters('To be, or not to be, that is the question.', 'e'));
Demo: Fiddle

incorrect variable declaration? or erratic modulo behavior?

why, in the following code, does modB always equal 1? ESPECIALLY considering b % 2 doesn't?
var b = 0;
var modB = 0;
function buttonState() {
b++;
modB = b % 2;
if (modB = 1) {
theButtonState = true;
} else {
theButtonState = false;
}
console.log(b%2);
console.log(modB);
console.log(theButtonState);
}
Change the following line of code:
if (modB = 1)
to
if (modB == 1)
and then try running the program again.
You can do it this way too as (Felix explained):
theButtonState = modB == 1;
Brevity in code improves its readability immensely.

How to change a variable to something if it's undefined?

I don't have my script completed yet or anything so I can't post the code. Basically I need a variable to change and keep going through a function increasing by one until it reaches its destination. Something like:
function one(a) {
var x = a;
var max = 3;
if (a < 3) {
// some code
two(x);
} else {
// function will end here quitting the whole thing and possibly other code
}
}
function two(x) {
var change = x+1;
one(change);
}
It all works how I need it but when I first enter function one how would I make it so when x = a doesn't have a value that it will by default be 0?
something like...
function one(a) {
var x = a;
var max = 3;
if (x = undefined) {
x = 0;
} else {
if (x < 3) {
// some code
two(x);
} else {
// function will end here quitting the whole thing and possibly other code
}
}
}
function two(x) {
var change = x+1;
one(change);
}
Any ideas?
You could do this:
function one(a) {
var x = a || 0;
if (x < 3) {
//debugger;
two(x);
} else {
// function will end here quitting the whole thing and possibly other code
alert('Done');
}
}
function two(x) {
x++;
one(x);
}
one();
FIDDLE
var x = a || 0 means x is a if a can be asserted as true or 0.
x++ means x = x + 1
You can check to see if the variable is defined and send it in the functions argument by using the short hand conditional.
typeof(a)=="undefined" ? 0 : a;
You can change your code to:
function one(a) {
var x = (typeof(a)=="undefined" ? 0 : a);
var max = 3;
if (x < 3) {
// some code
two(x);
} else {
// function will end here quitting the whole thing and possibly other code
return;
}
}
Fiddle: http://jsfiddle.net/gBBL2/
var x = (typeof a === 'undefined') ? 0 : a;
If a is undefined, use 0. Otherwise use a as the value of x.

Categories

Resources