Why is this while statement creating an infinite loop? - javascript

Without the if statement this loops works fine, however as soon as I add the if statement it turns it into an infinite loop-why? From my understanding continue should make the loop skip an iteration and then run as normal?
let num=0;
while(num<10){
if(num===4){console.log("skipping "+num);
continue;
}
console.log(num++);
}

You need also to increment the num in the if block. Without it after the if statement it never reaches to the num++ and you never change the value of num, so it stays 4 and every time goes into the if. You can add ++ in the if statement.
let num = 0;
while(num < 10) {
if(++num === 4) {
console.log("skipping " + num);
continue;
}
console.log(num);
}

Inside your while loop when num gets incremented to 4, it enters the if block and you are not incrementing num inside if block.
Also you are using continue which skips the code in the current iteration and moves to the next iteration. This keeps on happening and num is never incremented which leads to an infinite loop.
The following code prints numbers from 0 to 9 skipping 4 as asked in the question.
let num = 0;
while(num < 10) {
if(num === 4) {
console.log("skipping " + num++);
continue;
}
console.log(num++);
}

Related

Can someone help me understand the output of the following code?

I've tried but every time I get a different weird output. Ideally, it should print 0, 1, 2, 3, 4 and come out of the loop but it doesn't happen.
function foo(iteration) {
if (iteration === 5) {
return;
}
for (let i = 0; i < 5; i++) {
console.log(i);
foo(iteration + 1);
}
}
foo(0);
To understand the current output, start by walking through your function step by step. It helps me to write it out and keep track of the values.
iteration starts at 0
it starts the for loop
i is 0 at this point.
its logged to the console.
foo is called again with value of 1
iteration is still less than 5
a new for loop starts. (step 2)
i is 0, this is a brand new loop since it's inside of a new instance of foo
In each iteration of the for loop, you call foo and while iteration is less than 5 you start a new for loop.
Here is an example of a function that does what you like:
function foo(iteration) {
while(iteration < 5) {
console.log(iteration)
iteration++
}
}
foo(0)
You don't need to use recursion AND a loop. Just the loop itself will work.
for (let i = 0; i < 5; i++) {
console.log(i);
}
Or, just recursion:
function foo(i) {
if (i >= 5) return true;
console.log(i);
foo(i + 1);
}
foo(0);
What you're doing is saying:
While foo-iteration is less than 5, console.log five times and start up FIVE NEW incremented foo-iterations. Each of those 5 new foo-iterations will console.log five times on their own and start up FIVE NEW incremented foo-iterations, and so on until the foo-iterations finally reach 5. Do you see how this tailspins out of control?
Since you are already using recursion, there is no need to have that loop. Something like this should work:
function foo(iteration) {
if (iteration < 5) {
console.log(iteration);
foo(iteration + 1);
}
}
foo(0)

Function to restart a counter variable at zero when it is greater than an array's length -- not working

I am a novice developer trying to build an image carousel with html, css and javascript.
I have an array of images called 'slides' and variables called currentSlide, prevSlide, nextSlide that I want to use to keep track of the relevant slide index so that I can later display the proper slide as the values for the variables update.
I am trying to make it so the following will happen when the user clicks 'NEXT':
event listener calls a function called slideRight
slideRight will call 2 functions: updateVarsRight and displaySlides
updateVarsRight will increment the variables (ex. currentSlide) by 1
and then call another function called enforceLoop.
enforceLoop() will make sure the incremented variable values
do not move outside of the corresponding image array values. (i.e.
when currentSlide > slides.length-1, currentSlide = 0).
displaySlides will of course, display the new slides
The problem im having is with the enforceLoop function. If i check the console and click next, it seems that when currentSlide 's value is incremented past the total amount of slide in the array and is supposed to be set back to zero, it doesn't and continues to count upward.
It's hard for me to articulate but if you are able to run the codepen and check the console as you click next it should be clear what I mean.
I'm sure there are much better more efficient ways to build a slideshow but I was trying to figure things out on my own and this is the strategy I decided to go with and then look at refactoring afterwards.
Apologies if i haven't explained the issue clearly enough, first time poster.
Thanks in advance for any insight.
Codepen:
https://codepen.io/dansoutar/pen/RXZREV
Main issue:
function enforceLoop(num) {
if (num < 0) {
num === slides.length - 1;
console.log('num is now the last slide...' + num);
return num;
} else if (num > slides.length - 1) {
num === 0;
console.log(num + '...should be zero!!');
return num;
} else {
console.log('enforce loop = num is ...' + num);
return num;
}
}
num === slides.length - 1;, num === 0;
=== is an equality operator. You want to use the assignment operator =.
In Javascript, === is used for equality checking, so your lines at the beginning of each if case compare num to slides.length - 1 and 0 respectively; they do not assign to num. Change === for = in both of these places and enforceLoop should work correctly.
Corrected code:
function enforceLoop(num) {
if (num < 0) {
num = slides.length - 1;
console.log('num is now the last slide...' + num);
return num;
} else if (num > slides.length - 1) {
num = 0;
console.log(num + '...should be zero!!');
return num;
} else {
console.log('enforce loop = num is ...' + num);
return num;
}
}

Sum of Odd Fibonnaci failing with Higher values?

So im running into an odd error, where im summing all fibonnaci numbers that are odd and LESS than a number.
the odd thing is this works with low values, but when I get to upper values past 10 or so.....it'll crash codepen.io
here is what I have so far:
function f(n)
{
if(n <= 1)
return n;
return f(n-1)+f(n-2);
}
function sumFibs(num) {
var counter = 0;
var arr = [];
//Get all Fibbonaci Numbers up to num
for(let i = 1;i <= num;i++)
{
arr.push(f(i));
}
for(let j = 0;j < arr.length;j++)
{
if(arr[j] % 2 != 0 && arr[j] <=num)
{
counter+= arr[j];
}
}
console.log(counter);
return counter;
}
sumFibs(10);
Basically I calculate fib up to the num and then I go through each odd one thats less than or equal to num and add those up.
Im getting correct values (IE for 10 i get 10, for 4 i get 5....etc...)
but if I put in something like 1000 it seems to just crash? and I can't seem to figure out any reason why?
The recursive f() function is a logical way to express a Fibonacci number calculation, but it isn't very efficient compared to an iterative approach, especially because you are calling it repeatedly from inside a loop. I think this is bringing your browser to a halt. Within the loop each time you call f() it is calculating the specified Fibonacci number from scratch by recursively calling itself. So, say, to get f(10), it calls itself twice with f(9) + f(8) (and then they in turn call f(8)+f(7) and f(7)+f(6), etc., so even that is pretty inefficient), but in fact you already know what f(9) and f(8) are because you've stored those values in your array on previous loop iterations.
If you change your loop to calculate each subsequent number directly rather than calling another function you get much faster code:
var arr = [1, 1]; // start with the known first two numbers
//Get all Fibbonaci Numbers up to num
for(let i = 2; i < num; i++) // start the loop at index 2 for the third number
{
arr[i] = arr[i-2] + arr[i-1];
}
With that change in place, your sumFibs() function can give you results even for sumFibs(1000000) in a matter of milliseconds:
function sumFibs(num) {
var counter = 0;
var arr = [1, 1];
//Get all Fibbonaci Numbers up to num
for (let i = 2; i < num; i++) {
arr[i] = arr[i - 2] + arr[i - 1];
}
for (let j = 0; j < arr.length; j++) {
if (arr[j] % 2 != 0) {
counter += arr[j];
}
}
return counter;
}
console.log('10: ' + sumFibs(10));
console.log('100: ' + sumFibs(100));
console.log('1000: ' + sumFibs(1000));
console.log('10000: ' + sumFibs(10000));
console.time('High fib');
console.log('1000000: ' + sumFibs(1000000));
console.timeEnd('High fib');
Note that you also had a logic error in your second loop, the one that adds up the odd numbers: the && arr[j] <=num part needed to be removed. The values in arr are the actual Fibonacci numbers, but num is the sequence number, so it doesn't make sense to be comparing them. You just want every odd number in the whole array.
However, the return value from your function is still going to be incorrect if num is too large. That's because by the time you get to the 80-somethingth Fibonacci number it is larger than JavaScript can handle without losing precision, i.e., larger than Number.MAX_SAFE_INTEGER, 9,007,199,254,740,991 (which is 2^53 - 1). Numbers above that start getting rounded so your tests for odd numbers aren't reliable and thus the total sum doesn't include all of the numbers it should have, or if you add too many JS considers your result to be Infinity.

Javascript for loop with iterator In the middle and decrement operator to the left of i?

For a non-recursive example of a factorial function I found this example and am having a little difficulty tracing through the code:
function fact(x) {
if(x == 0) {
return 1;
}
if(x < 0 ) {
return undefined;
}
for(var i = x; --i; ) {
x *= i;
}
return x;
}
I don't understand the syntax of this for loop-- why is the iteration statement in the middle, shouldn't that be where the test condition normally is? Does that mean there is no test condition or no iteration statement? You can leave one or both out?
Secondly, what is the difference in having ++i or --i in a for loop as opposed toi++ and i--?
If I wanted to find fact(5), in the first iteration of the for loop, is i 4 or 5?
In js, 0 means false, and the other values like 1 are true.
why is the iteration statement in the middle
for(var i = x; --i; /* optional */ )
^^ its decrement as well as the condition
loop continues until, i is 0
In fact, you can create infinite loop
for(;;);
I wanted to find fact(5), in the first iteration of the for loop, is i
4 or 5?
for(var i = x /* i=5 */; --i/* i=4 */; ) {
x *= i;/* i=4 */
}
In JavaScript, 0 evaluates as false. What's done here is to omit the iteration part of the loop, and have the test part perform the iteration itself. --i first decreases the value of i by 1, and then the for loop evaluates it, executing only if it's not 0.
The difference between i-- and --i is that --i first subtracts 1 from i and then evaluates i, while i-- first evaluates i and then subtracts 1 from i.
for example:
var i=5;
console.log(i--);
will print 5, while:
var i=5;
console.log(--i);
will print 4.
I guess there is something wrong in the for loop as if you are trying to get the factorial of the number you should stop decreasing the number when it reaches 2.
So the for loop should be something like this
for(var i = x; i > 2;--i) {
x *= i;
}
Also the first if statement should be
if(x == 0 || x == 1) {
return 1;
}
The difference between i-- and --i is that
i-- decrements i at the end of the loop iteration while --i decrements it before the iteration start.
So in the first iteration i is equals to 4 when you try to get fact(5).

JS - Prime numbers script - explanation

I'm learning JS and stumbled upon a script to output the prime numbers < 100 . But I'm not sure I fully understood how it works. If somebody could explain it, I would be glad. :)
So here it is:
for (var counter = 0; counter <= 100; counter++)
{
for (var i = 2; i <= counter-1; i++)
if (counter%i === 0) break;
if(i === counter)
console.log(counter);
}
Primes are by definition only divisible by themselves and 1.
The outer loop for var(counter = 0; ...) loops through the numbers from 0 to 100.
The inner loop for (var i = 2; ...) then tries to divide the outer number by every number between 2 and the counter's value. If any of them divide the number without a remainder the loop is broken. That's the if (counter%i === 0) break; line.
If we broke out of loop and i === counter, it's a prime, else it's not - by definition.
/* For every number from 0 to 100, do the following: */
for (var counter = 0; counter <= 100; counter++)
{
/* Loop through values from 2 to 1 before the counter. */
for (var i = 2; i <= counter-1; i++) {
/* if the remainder of dividing counter by the current value of `i` is zero,
* we know we don't have a prime, so break out of the loop:
*/
if (counter%i === 0) break;
}
/* If the loop completed and `i` is equal to the counter, that means counter is not
* divisible by anything except for 1 and itself, making it prime
*/
if(i === counter)
console.log(counter);
}
I'm not sure how much JavaScript you know, so some of this might be really basic.
First, remember that a prime number is one whose only factors are 1 and itself.
So the first line says it loops from 0 to 100, with counter as the variable holding this number.
The next line for (var i = 2; i <= counter-1; i++) loops from 2 to counter-1 (notice it excludes 1 and counter) and uses i to hold this number.
Next, if (counter%i === 0) break; tests whether counter is divisible by i: the remainder operator % returns the remainder (like from long division), e.g. 11 % 3 will return 2 because 11 divided by 3 gives 3 remainder 2; if the remainder counter % i is 0 (=== is a stricter equality than ==, but that's a different answer altogether) that means that counter is divisible by i and so is not prime. The break statement tells it to exit the innermost loop (that is, the loop over i), so the program increments counter and goes on.
If the previous line did not break for any value of i, then counter is prime — specifically, at the end of the loop body, i is incremented (now equal to counter), the statement i <= counter-1 evaluates to false, and the loop ends. So now i === counter is true, so console.log(counter) shows this value in the console.

Categories

Resources