Reputation: 2148
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);
}
Upvotes: 2
Views: 9609
Reputation: 664599
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);
Upvotes: 2
Reputation: 776
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.
Upvotes: 2
Reputation: 4023
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.
Upvotes: 3
Reputation: 82287
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.
Upvotes: 2
Reputation: 388316
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);
}
}
Upvotes: 2
Reputation: 7511
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.
Upvotes: 2