JS - Why does the order of this if/else matter? - javascript

Why would this not work if I took the first "if" statement and put it as the third "else if" statement? Just want to understand. Thanks!
function fizzBuzz(num) {
if ((num % 3 === 0) && (num % 5 === 0)) {
return 'fizzbuzz';
} else if (num % 3 === 0) {
return 'fizz';
} else if (num % 5 === 0) {
return 'buzz';
} else {
return num;
}
// if num is divisible by 3 return 'fizz'
// if num is divisible by 5 return 'buzz'
// if num is divisible by 3 & 5 return 'fizzbuzz'
// otherwise return num
}

If-else-if statement only work until one of the if statements becomes true.
This scenario prevents to check other "else if" conditions.
In your second scenario if modulus of "num" is 0 for 3 OR 5, it will stop checking other else if statements,
It is necessary to prioritize the sequence of if-else-if conditions.

So a if/else if statement works so that as soon as one of the ifs is true, it executes the code inside that if statement and then skips the rest of the ifs and else statements. In this case, however, the return ends the function and therefore it skips the rest of the code in the method.

If else if checks each condition on by one. If any of the conditional blocks executes, the rest of the conditions won't work.
function fizzBuzz(num) {
if ((num % 3 === 0) && (num % 5 === 0)) {
return 'fizzbuzz';
} else if (num % 3 === 0) {
return 'fizz';
} else if (num % 5 === 0) {
return 'buzz';
} else {
return num;
}
// if num is divisible by 3 return 'fizz'
// if num is divisible by 5 return 'buzz'
// if num is divisible by 3 & 5 return 'fizzbuzz'
// otherwise return num
}
In your example, if you put the first condition in the third block, i.e, else if, if the number is divisible by either 3 or, 5, the corresponding conditional block work and resulting in skipping the third block. The order of execution is important in if-else-if ladder.

Yes Remember that if/else-if/else executes in order and will stop when it finds an acceptable case. In your example, if (num % 3 === 0) you'll return return 'fizz' and that condition is true. So This is (num % 5 === 0) and (num % 3 === 0) && (num % 5 === 0)) are not mutually exclusive - they can both be true, so the order matters.

Related

I am doing an if statement with multiples of a number

I am doing an exercise, the problem is that my if/else structure does not work properly and I do not know why.
Here is the exercise statement and my code
Your task is to write a function, fizzBuzz, that accepts a number and returns a string:
'fizz' if the number is divisible by 3;
'buzz' if the number is divisible by 5;
'fizzbuzz' if the number is divisible by both 3 and 5.
'{number}' if the number doesn't fulfil any of the above conditions.
function fizzBuzz(number) {
if (number % 3 === 0) {
return "fizz"
};
if (number % 5 === 0) {
return "buzz"
};
if (number % 3 === 0 && number % 5 === 0) {
return "fizzbuz"
};
else return number
}
Try a little mental debugging. Look at your code and run different values through it in your mind:
What happens if you run the value 6 through it?
What happens if you run the value 10 through it?
What happens if you run the value 15 through it?
Ask yourself, "How could I fix this?" (hint: order of operations is important).
Something like this would do what you expect:
function fizzBuzz(n) {
const fizz = n % 3 ? '' : 'fizz' ;
const buzz = n % 5 ? '' : 'buzz' ;
return !fizz && !buzz ? '{number}' : `${fizz}${buzz}` ;
}
or this:
function fizzBuzz( n ) {
let s;
if ( n % 3 === 0 ) {
s = 'fizz' ;
if ( n % 5 === 0 ) {
s = 'fizzbuzz' ;
}
} else if ( n % 5 == 0 ) {
s = 'buzz' ;
} else {
s = '{number}' ;
}
return s;
}
This does [at most] 2 divisions and 2 comparisions.
The former does 2 divisions and 3-4 comparisons, so it is nominally less efficient.
But I know which version I'd rather look at.
The problem is, if a number is divisible by 5 and 3 (ex 15) "fizz" would only be returned (as a factor of 3) because every block {...} terminates the function with a return (this technique is called a "short-circuit", which isn't a bad practice). So you need to put the 5 and 3 condition first. Also that condition had an undefined variable called solution so that would've been the first error. One minor thing is that each block {...} was suffixed with a semi-colon: ; which is just bad formatting but it doesn't affect functionality.
function fB(number) {
if (number % 3 === 0 && number % 5 === 0) {
return "fizzbizz";
}
if (number % 3 === 0) {
return "fizz";
}
if (number % 5 === 0) {
return "bizz";
}
return number;
}
console.log(fB(15));
console.log(fB(575));
console.log(fB(49));
console.log(fB(51));
console.log(fB(80));
console.log(fB(375));
console.log(fB(99));
console.log(fB(Infinity));

JS - Appending a logged sequence of numbers

I've made a sequence of numbers from 0 to 20 and I want to change the sequence so once it comes up with a multiple of 3 and 5 it logs 'FizzBuzz' to the terminal then carries on with the rest of the numbers up to 20. My problem is once I have changed the number to the string the rest of the terms in the sequence come up with NaN. I know the problem with my code is that I'm changing the number to a string and you cannot perform addition to a string which is why NaN comes up. I'm pretty new to this so any thoughts on how to do complete this would be greatly appreciated. I've tried using .append() but I'm pretty sure I'm using it incorrectly.
My code thus far;
var increment = function(number)
{
for (var i = 1; i <= 20; i++)
{
console.log(number++)
if ((number % 3 === 0) && (number % 5 === 0))
{
number = "FizzBuzz"
console.log("FizzBuzz");
}
else if (number % 3 === 0)
{
console.log("Fizz");
}
else if (number % 5 === 0)
{
console.log("Buzz");
}
else
{}
}
}
increment(1)
When you find a multiple of 3 and 5, you are setting number to "FizzBuzz", which does not have a ++ operator. On the next iteration, you call ++ on number, which is now "FizzBuzz", so it logs NaN.
If you don't set number to "FizzBuzz" it should work fine.
This would do it
var increment = function()
{
for (var i = 1; i <= 20; i++)
{
if ((i % 3 === 0) && (i % 5 === 0))
{
console.log("FizzBuzz");
}
else if (i % 3 === 0)
{
console.log("Fizz");
}
else if (i % 5 === 0)
{
console.log("Buzz");
}
else{
console.log(i)
}
}
}
increment()
There's no need to pass the number parameter, since your for loop is already set to increment by 1 (i++).

for cycle and if statements

I've encountered some misundertanding. There is a for cycle with some if statements:
for (var number = 1; number < 100; number++) {
if (number % 3 == 0 && number % 5 == 0)
console.log(number + "fizzbuzz");
if (number % 5 == 0)
console.log(number + " buzz");
if (number % 3 == 0)
console.log(number + " fizz");
else console.log(number);
}
The output of this code is 1, 2, 3 fizz, 4, 5 buzz, etc. So it's what expected.
But if we delete braces the output will be like this:
15fizzbuzz
30fizzbuzz
45fizzbuzz
60fizzbuzz
75fizzbuzz
90fizzbuzz
100 buzz
100
Also, there is a second implementation of this program(with the right-way if-else statements):
for (var number = 1; number < 100; number++)
if (number % 3 == 0 && number % 5 == 0)
console.log(number + "fizzbuzz");
else if (number % 5 == 0)
console.log(number + "buzz");
else if (number % 3 == 0)
console.log(number + "fizz");
else console.log(number);
Notice that there are no braces too, but the output is ok.
Can you explain, what's the difference?
When you miss a semicolon or brackets, javascript tries to insert it on its own, & at times can produce some weird results like this. (Which is correct by the rules, just humans & machine don't agree on how to process it :D )
When you remove braces of for loop javascript tries to puts braces in code & run it, this is different that how you expect it to behave thus you are confused!
What you wrote & read:
for (var number = 1; number < 100; number++)
if (number % 3 == 0 && number % 5 == 0)
console.log(number + "fizzbuzz");
if (number % 5 == 0)
console.log(number + " buzz");
if (number % 3 == 0)
console.log(number + " fizz");
else console.log(number);
What javascript did with it & executes:
for (var number = 1; number < 100; number++){ //runs loop here
if (number % 3 == 0 && number % 5 == 0){
console.log(number + "fizzbuzz"); //prints for first condition
}
}
//now number is 100!
if (number % 5 == 0){
console.log(number + " buzz"); //prints for second condition once cause 100%5==0 is true
}
if (number % 3 == 0){
console.log(number + " fizz");
}
else{
console.log(number); //prints for this else condition once cause 100%3==0 is false
}
Which is perfectly valid & there is no error or bug here!
This happens because if the is no immediate else after if then javascript terminate that statement there, but if you use else...if then it continues that statement till if find a else or a statement not followed by else
If you want to play with this type of behaviour use Google Closure Compiler to see how code is interpreted by machine.
NOTE: As #carcigenicate suggest in comments, Always use braces!
As a lot of comments pointed out, its the lack of elses ( or blocks ) in your first code that make it going wrong.
//a bit shortified to make it clearer
var a=true,b=true;
if(a && b){ }// will be executed
if(a){ } //will be executed
if(b){} //will be executed
//vs.
if(a&&b){}//will be executed
else if(a){}//else => not executed
else if(b){}//else => not executed
However, it might be better to restructure your code as its quite repetitive:
for (var number = 1; number < 100; number++)
console.log(number+ (number % 3 == 0?"fizz":"")+ (number % 5 == 0?"buzz":""));
So log the number, if its a multiple of 3 add "fizz" and if its an multiple of 5 add "buzz"...
The syntax of a for loop is for (statementA; statementB; statementC) statementD. Statements can be grouped together with {}, so {statement, statement, ...} can be used where a single statement is expected.
for (var number = 1; number < 100; number++) {
if (number % 3 == 0 && number % 5 == 0)
console.log(number + "fizzbuzz");
if (number % 5 == 0)
console.log(number + " buzz");
In this case statementA is var number = 1, statementB is number < 100, and statementC is number++ and statementD is if (number % 3 == 0 && number % 5 == 0) console.log(number + "fizzbuzz"). The second if is another statement that does not belong to the for loop. If you want for the second if statement to belong to the for loop, you need to use {} to group the statements together.
The syntax of a if statement is if (expression) statement or if (expression) else statement. Using several if else aligned you are able to pass the first statement to the for loop, the second statement is going to belong to the first if that still belongs to the for loop. That is why the last example works without {}.
It is important to note that the code may work, but it is still bad code. It is recommended to use {} to group the statement from below for for, while, and if even if it is a single statement.
You may want to learn the JavaScript syntax before trying to understand JavaScript code. https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps

using an if statement inside a while loop

I just figured out how to test for certain conditions and modify output within a loop. But I noticed that testing for two conditionals with the && operator only works in an if/else if/else if/else chain if it's the first one tested for.
Can someone explain why this works:
var number = 0;
var counter = 0;
while (counter < 100) {
number ++;
counter ++;
if (number % 3 == 0 && number % 5 == 0)
console.log ("FizzBuzz");
else if (number % 3 == 0)
console.log("Fizz");
else if (number % 5 == 0)
console.log("Buzz");
else
console.log(number);
}
But this does not?:
var number = 0;
var counter = 0;
while (counter < 100) {
number ++;
counter ++;
if (number % 3 == 0)
console.log("Fizz");
else if (number % 5 == 0)
console.log("Buzz");
else if (number % 3 == 0 && number % 5 == 0)
console.log ("FizzBuzz");
else
console.log(number);
}
An else if, as the name suggests, will only execute when a previous if fails. So the statement else if (number % 3 == 0 && number % 5 == 0) will execute only when if (number % 3 == 0) and else if (number % 5 == 0) fail. If a number is a multiple of 3 and 5 both, then the first if gets successfully executed, and the rest ifs and else-ifs are ignored.
However, in code 1, the ordering of ifs and else-ifs is such that, if a number is divisible by both 3 & 5, then first if is executed, if it is divisible by the only 3, then first if is not executed, only else if (number % 3 == 0) is executed.
Let's make an example using the numbers 6, 10, 15.
The number 6 will execute - in your first example (the working example) - the second if block because in the first one the condition will not be satisfied while the third and fourth block will be ignored, and - in your second example (the not-working example) - will execute the first if block and ignore the other blocks that follow.
The number 10 will execute - in your first example - the third block because the first's and second's condition is not satisfied while the fourth block will be ignored, and - in your second example - will execute the second block, because the condition in the first block is not satisfied, while the blocks that follow will be ignored.
The number 15 will execute - in your first example - the first block and ignore the blocks that follow, and - in your second example - will also execute the first block because the condition is satisfied while the blocks that follow will be ignored.
So, to recap, in your second example, the third if block will never be executed because the condition for its execution is made up of an and of the first and second if block's conditions. In order for the third block to be executed you would need a case where the first if block's condition (let's say c1) and the second if block's condition (let's say c2) are false and c1 && c2 is true, but in order to have c1 && c2 to true you need c1 and c2 to be true, which leads to the execution of the first block and skipping of the rest.
You want to test for if the the number is divisible by three and five, but before you do that you test if it is just divisible by three.
It is, so it follows that branch of logic and never attempts to test if it is divisible by three and five.
Because in your test if the number is a multiple of 3 or 5 then the corresponding if statemetn will get executed before the number % 3 == 0 && number % 5 == 0 statement is reached so it will never get executed.
Let us assume the number is 33, the the first test will become success which is correct, but if the number if 15 then again the first if is success because 15 is a multiple of 3 so even though it is a multiple of 5 also the 3rd condition will not get a chance to execute
To get it correct you may need something like below, where if the number is a multiple of both the versions we skip first 2 conditions
var number = 0;
var counter = 0;
while (counter < 100) {
number++;
counter++;
if (number % 3 == 0 && number % 5 != 0) {
console.log("Fizz");
} else if (number % 5 == 0 && number % 3 != 0) {
console.log("Buzz");
} else if (number % 3 == 0 && number % 5 == 0) {
console.log("FizzBuzz");
} else {
console.log(number);
}
}
Everything that is either evenly divisible by 3 or evenly divisible by 5 has been removed in the second version. By the time it checks to see if a number is divisible by 3 and divisible by 5 there is no chance of it being true because one of the first two clauses already evaluated to be true.
Consider this pseudo code
if( A || B ) return;
if( A && B ) //this code will never execute
and then consider A to be number % 3 == 0 and B to be number % 5 == 0. This is essentially what is happening, and why the last if statement never executes.
What you actually want to test is
if (number % 3 == 0 && number % 5 == 0) …
else if (number % 3 == 0 && number % 5 != 0) …
else if (number % 3 != 0 && number % 5 == 0) …
else if (number % 3 != 0 && number % 5 != 0) …
if you'd write out the four cases.
Only you don't need to be that explicit, because when the previous conditions already did not match (and you are in the else branch), then those != 0 are implied and you can omit them. However, order matters, as the conditions are tested consecutively.
So if you have the fully qualified conditions, you can shuffle their order as you want:
if (number % 3 == 0 && number % 5 != 0) … // move to front
else if (number % 3 != 0 && number % 5 == 0) …
else if (number % 3 == 0 && number % 5 == 0) …
else if (number % 3 != 0 && number % 5 != 0) …
and then continue to simplify conditions, omitting the parts that are already implied by their parent cases:
if (number % 3 == 0 && number % 5 != 0)
console.log("Fizz");
else if (number % 3 != 0 && number % 5 == 0) // (an == instead of the && would suffice)
console.log("Buzz");
else if (number % 3 == 0) // as it didn't match the first condition, we know that % 5 == 0
console.log("FizzBuzz");
else // here we know that % 3 != 0 && % 5 != 0
console.log(numer);
Other permutations of the condition let us use as few as in your original example, like
if (number % 3 == 0 && number % 5 != 0)
console.log("Fizz");
else if (number % 3 == 0) // as it didn't match the first condition, we know that % 5 == 0
console.log("FizzBuzz");
else if (number % 5 == 0) // as it didn't match the first condition, we know that % 3 != 0
console.log("Buzz");
else // here we know that % 3 != 0 && % 5 != 0
console.log(numer);
And the minimum number of tests would be achievable by nesting them:
if (number % 3 == 0)
if (number % 5 == 0)
console.log("FizzBuzz");
else
console.log("Fizz");
else
if (number % 5 == 0)
console.log("Buzz");
else
console.log(numer);

Why doesn't my if / else statement work properly?

I am trying to iterate through the arrays in the numbers variable, and if a number can be divided by 3 I'm logging "fizz", if it can be divided by 5 I'm logging "buzz", and if a number can be divided by 3 + 5, or 15, I'm logging "fizzbuzz"
Here is the working code:
var numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for (var i = 1; i <= numbers.length; i++) {
if (i % 15 === 0) {
console.log("FizzBuzz");
} else if (i % 5 === 0) {
console.log("Buzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else {
console.log(i);
}
};
Here is my original code, which doesn't log "fizzbuzz"
var numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
for (var i = 1; i <= numbers.length; i++) {
if (i % 5 === 0) {
console.log("Buzz");
} else if (i % 3 === 0) {
console.log("Fizz");
} else if (i % 15 === 0) {
console.log("FizzBuzz");
} else {
console.log(i);
}
};
Why does the (i % 15 === 0) condition need to precede the other two conditions? Shouldn't it not matter?
The number 15 is divisible by both 3 and 5. If you don't test it first, then you'll never get there.
So let's take 30 as an example. If you check 15 first, you'll see that it's divisible by 15. However, if you check either 5 or 3 first, it'll be flagged as being divisible by either of those.
After one of your conditions evaluates as true, you break out of that if-block and don't evaluate following else-if/else statements. If you want the rest of them to evaluate you can make them if statements instead of else-if's.
It's because firstly the computer checks for the first statement and then the others as you use the ELSE IF which means, to check the statement after the first one is false. Use IF for all instead.

Categories