understanding the fizz buzz in C# [closed]

2019-03-06 11:36发布

问题:

When solving "fizz-buzz" in C# using a "while" loop, I found out that first I should find the multiples of both 3 and 5 (multiples of 15) and then go to the multiples of 3 and 5 like below.

int myval = 0;

while (myval < 100)
{
    myval = myval + 1;

    if (myval % 15 == 0)
    {
        listBox1.Items.Add("fizzbuzz");
    }
    else if (myval % 3 == 0)
    {
        listBox1.Items.Add("fizz");
    }
    else if (myval % 5 == 0)
    {
        listBox1.Items.Add("buzz");
    }
    else
    {
        listBox1.Items.Add(myval);
    }
}

But if I write the code to filter multiples of 3 and 5 first and then go to the multiples of both 3 and 5 (multiples of 15) like below the end result only shows the fizz (multiples of 3) and buzz (multiples of 5) without fizz-buzz (multiples of both 3 and 5). Does anyone know what's the reason for this even IDE doesn't show me any errors.

myval = 0;

while (myval < 100)
{
    myval = myval + 1;

    if (myval % 3 == 0)
    {
        listBox1.Items.Add("fizz");
    }
    else if (myval % 5 == 0)
    {
        listBox1.Items.Add("buzz");
    }
    else if (myval % 15 == 0)
    {
        listBox1.Items.Add("fizzbuzz"); // for multiples of both 3 and 5  
    }
    else
    {
        listBox1.Items.Add(myval);
    }
}

回答1:

This boils down to the fact that if-else statements are processed sequentially. As soon as a condition that evaluates to true is encountered, the other else if clauses are skipped.

Suppose that a and b are both true. When you write

if (a) {
    Foo1();
}
else if (b) {
    Foo2();
}

you do not execute both Foo1 and Foo2. Since a is true, Foo1 executes and b is not even evaluated.

Now consider your problem. Consider the number 15. All three candidate divisors, 3, 5 and 15, divide into that number.

if (myval % 3 == 0)
{
    listBox1.Items.Add("fizz");
}
else if (myval % 5 == 0)
{
    listBox1.Items.Add("buzz");
}
else if (myval % 15 == 0)
{
    listBox1.Items.Add("fizzbuzz"); // for multiples of both 3 and 5  
}
else
{
    listBox1.Items.Add(myval);
}

Since the multiples of 15 are also multiples of 3 (and 5), you will never even reach the myval % 15 == 0 test for multiples of 15.



回答2:

Because it satisfies the first two conditions. So it will never hit your third else statement.



回答3:

It's because something divisible by 3 and 5 is also divisible by 3 and by 5. If you catch either of those conditions first, the later condition is never checked.

You could also write it like so:

var resultString = "";
if(myval % 3 == 0) resultString += "fizz";
if(myval % 5 == 0) resultString += "buzz";
if(myval % 5 != 0 && myval % 3 != 0) resultString += myval;
listBox1.Items.Add(resultString);

This will print all conditions without needing a separate check for % 15.

Also, I know this wasn't the original question, but typically someone wouldn't use a while loop to cycle through a range of numbers. Use a for loop for that:

for( int myval = 0; myval <= 100; myval++)
{
    // code goes here
}


回答4:

I always solved this a slightly different way: by constructing the string to add.

for (int myVal = 0; myVal < 100; myVal++)
{
    string fb = "";

    if ((myVal % 3) == 0) { fb = "fizz"; }
    if ((myVal % 5) == 0) { fb += "buzz"; }

    // Handle the case where it isn't divisible by 3 or 5:
    if (fb == "") { fb = myVal.ToString(); }

    // "output" the string.
    listBox1.Items.Add(fb);
}


回答5:

You can use this method to fill your Listbox:

    foreach (int i in Enumerable.Range(1,100)){
        string str = null;
        listBox1.Items.Add((str = (i % 3 == 0 ? "fizz" : "") 
                                + (i % 5 == 0 ? "buzz" : "")) == "" 
                               ? i.ToString() : str );
    }