Doubt in While with two conditions

Asked

Viewed 5,665 times

1

I have an exercise to do and I have a problem in while. The pro condition while end would be when it went through 20 even numbers and 20 odd numbers, but when it reaches the first condition (contImpar == 20, that is, it arrives in 39), it stops of repeating. Where is the error? It follows the excerpt of the code and the enunciation:

Create an algorithm that adds the first 20 odd integers and print the sum of these. Also show the product of the first 10 even numbers.

int contPar=0, contImpar=0, somaPar=0, somaImpar=0, aux=1;

while( (contImpar<20) && (contPar<20) ) {
    printf("%d: ", aux);
    if(aux % 2 == 0) {
        contPar++;
        printf("%d + %d = ", somaPar, aux);
        somaPar += aux;
        printf("%d   qtd par: %d\n", somaPar, contPar);
    } else {
        contImpar++;
        printf("%d + %d = ", somaImpar, aux);
        somaImpar += aux;
        printf("%d   qtd impar: %d\n", somaImpar, contImpar);
    }
    aux++;
}
  • Your interpretation of the exercise is wrong. You have something to indicate that you only have to use one while? It’s a complicated logic for nothing.

  • 1

    exchange && for ||

2 answers

4


Under stopping condition, while, semantics of the language and the title of the question

Like the @Maniero spoke, the error lies in its interpretation and how to express it in the programming language.

In , we express the condition of continuity, not stopping. So, if the stopping condition is:

contImpar >= 20 && contPar >= 20

if we deny it we will have the condition of continuity:

!(contImpar >= 20 && contPar >= 20)

Applying Morgan’s:

!(contImpar >= 20) || !(contPar >= 30)

Knowing that "lesser-than" is the complement of "greater-equal":

contImpar < 20 || contPar < 20

As the comment of @Felipe.

So to do the magic,

while (contImpar < 20 || contPar < 20)

On the problem contained in the question and search of the first numbers

(Credits to @Maniero for noting the lack of such an explanation).

First, on the text of the question:

Create an algorithm that adds the first 20 odd integers and prints the sum of these. Also show the product of the first 10 even numbers.

At no time is specified which type of iteration will be used. It also does not say that it should be performed in a single iteration. Nor that the iteration should be done incrementally. (Actually, it does not need iteration, just check the Reply by @Andersoncarloswoss for the sum formula).

Are we going to solve this question in several ways? But first, let’s look at some properties of summations and products.

About the number 0 and its parity

The number 0 is an even number because 0 % 2 == 0. Thus, considering the number of naturals from the 0, He’d be the first even number. However, since it is the absorbing element of multiplication, the result of any product that includes it would be trivially 0.

As this is tedious, the result should not be trivially 0.

(Credits to @Andersoncarloswoss for noting the lack of such an explanation).

Sums and products

A sum is a sum over a set of items. This can be defined recursively:

somatório(lista):
  se lista.tamanho() == 0:
    retorne 0
  senão:
    último_elemento = lista.cauda()
    lista.remove_cauda()
    retorne somatório(lista) + último_elemento

Note that the sum of an empty set is 0. This is useful because zero is the neutral element of the sum. It was necessary to create this case for the recursion to come to an end.

However, this can be done iteratively, it does not need to be done recursively. To treat this iteratively, we need to find a way to accumulate the sum value, as if it were recursion.

First, let’s try to mathematically express the call to somatório({a, b, c, d}), opening the recursion as needed:

somatório({a, b, c, d}) =
somatório({a, b, c}) + d =
(somatório({a, b}) + c) + d =
((somatório({a}) + b) + c) + d =
(((somatório({}) + a) + b) + c) + d =
((((0) + a) + b) + c) + d

Note how we start from 0, then we accumulate with the first element, then the second, until the last element. This could be described algorithmically as follows:

somatório(lista):
  acc = 0
  para i = 0; i < lista.tamanho(); i++:
    acc += lista.elemento(i)
  retorne acc

For the product, simply change the operation and the neutral element. In this case, the neutral element is 1:

produtório(lista):
  se lista.tamanho() == 0:
    retorne 1
  senão:
    último_elemento = lista.cauda()
    lista.remove_cauda()
    retorne produtório(lista) * último_elemento

Doing the same recursion break-up that we did earlier, we have the following:

produtório({a, b, c, d}) =
produtório({a, b, c}) * d =
(produtório({a, b}) * c) * d =
((produtório({a}) * b) * c) * d =
(((produtório({}) * a) * b) * c) * d =
((((1) * a) * b) * c) * d

Similarly, we can make the following accumulation for the productive:

produtório(lista):
  acc = 1
  para i = 0; i < lista.tamanho(); i++:
    acc *= lista.elemento(i)
  retorne acc

Separate iteration, for, iterating on multiplicity index

To get the first 20 odd numbers, we should start with the number 1, and the next will be 1 (+2) = 3, and the following 1 (+2+2) = 5 etc. If analyzed, the formula of x-nth odd number is ímpar(x) = 1 + 2*x. Since we want the first 20 odd numbers, we can make the following iteration:

int i;
for (i = 0; i < 20; i++) {
  int impar = 1 + 2*i;
  printf("%d-esimo numero impar: %d\n", i + 1, impar);
}

Even numbers follow a similar formula, but begin with 2. Therefore, par(x) = 2 + 2*x. So the first 10 even numbers would be like this:

int i;
for (i = 0; i < 10; i++) {
  int par = 2 + 2*i;
  printf("%d-esimo numero par: %d\n", i + 1, par);
}

Therefore, to make the sum of the first 20 odd numbers and the output of the first 10 even numbers:

int i;
int acc_soma = 0;
int acc_produto = 1;
for (i = 0; i < 20; i++) {
  acc_soma += 1 + 2*i;
}
for (i = 0; i < 10; i++) {
  acc_produto *= 2 + 2*i;
}
printf("soma dos primeiros 20 impares: %d\n", acc_soma);
printf("produto dos primeiros 10 pares: %d\n", acc_produto);

Separate iteration, for, iterating on the set of numbers

The previous option is the most obvious one for me. However, I can do the iteration differently. Instead of iterating over the index and only then calculating the number, I can iterate directly over the numbers.

So the first 20 odd ones would be iterated like this:

int i;
for (i = 1; i < 1 + 20*2; i += 2) {
  int impar = i;
  printf("novo impar: %d\n", impar);
}

For pairs:

int i;
for (i = 2; i < 2 + 10*2; i += 2) {
  int par = i;
  printf("novo par: %d\n", par);
}

So the answer would be this way:

int i;
int acc_soma = 0;
int acc_produto = 1;
for (i = 1; i < 1 + 20*2; i += 2) {
  acc_soma += i;
}
for (i = 2; i < 2 + 10*2; i += 2) {
  acc_produto *= i;
}
printf("soma dos primeiros 20 impares: %d\n", acc_soma);
printf("produto dos primeiros 10 pares: %d\n", acc_produto);

Unified iteration, while, iterating incrementally

Well, here we make use of the stopping condition you put in the question. As in the language we do not describe stop condition, but continuity condition. So let’s use the while described in the first section of this reply:

while (contImpar < 20 || contPar < 20)

To mark that only 10 even numbers will be required, I will use the while as follows:

while (contImpar < 20 || contPar < 10)

To make the iteration complete, let’s start from the number 1 and start from the first. Basically, the same one you used, I’ll start with it. Only I’ll use i in place of aux. I will also ensure that it will only go to the accumulator if it is within the necessary intervals (i.e., even to the tenth, odd to the twentieth).

int contPar = 0;
int contImpar = 0;
int produtoPar = 1;
int somaImpar = 0;
int i = 1;

while (contImpar < 20 || contPar < 10) {
  if (i % 2 == 0) {
    if (contPar < 10) {
      contPar++;
      produtoPar *= i;
    }
  } else {
    if (contImpar < 20) {
      contImpar++;
      somaImpar += i;
    }
  }
  i++;
}
printf("soma dos 20 impares: %d\n", somaImpar);
printf("produto dos 10 pares: %d\n", produtoPar);

Unified iteration, while (1), iterating incrementally, end of iteration with break

Now, more to a matter of academicism. We cannot put a stop condition on while, there’s no way out of it. In return, we can place a parole with a break.

int contPar = 0;
int contImpar = 0;
int produtoPar = 1;
int somaImpar = 0;
int i = 1;

while (1) {
  if (contImpar >= 20 && contPar >= 10) {
    break;
  }
  if (i % 2 == 0) {
    if (contPar < 10) {
      contPar++;
      produtoPar *= i;
    }
  } else {
    if (contImpar < 20) {
      contImpar++;
      somaImpar += i;
    }
  }
  i++;
}
printf("soma dos 20 impares: %d\n", somaImpar);
printf("produto dos 10 pares: %d\n", produtoPar);
  • 1

    A different way of showing it. I hope the AP knows De Morgan +1

  • @Amadeus you gave me the idea to link to some reference. I can’t take it for granted that the AP knows everything, right? Or who stops here later?

  • 1

    Still the code does not do what the statement asks. But I gave +1 because it solves what he asks.

  • @bigown the AP had focused a lot of energy on the loop part, so I ended up focusing only on that; I’m going to edit and put the rest that does the desired. Thanks for the feedback

  • @bigown, replied to

  • 1

    Perhaps it is interesting to say that the number zero is an even integer, but it was disregarded just for asking for the product of the numbers and not making much sense, since it would always give zero. The correct statement would indicate "even positive integers".

  • @Andersoncarloswoss, a certain amount of sloth involved. Thank you for the feedback. I’ll do it right away

  • @Andersoncarloswoss, adjusted

Show 3 more comments

1

Taking advantage of all the commitment that Jefferson had to his reply, I propose a more mathematical analysis of the problem. As he commented, the statement itself in the problem does not explicitly say that loops should be used in the solution. This is usually the first solution to be considered, but not the only one.

We know that an odd positive integer can be represented as:

x = 2*i-1, para i = 1, 2, 3, ...

Thus, we can say that if we consider N odd numbers, the latter will be 2*N-1 and the sum of these would be:

S = 1 + 3 + 5 + 7 + ... + (2*N-1)

By mathematically analyzing the sequence, we can see that this sum is nothing more than the sum of elements of a progression of integers that grow at a ratio equal to 2. In mathematics, we call it arithmetic progression (PA) and the sum of finite elements of a PA has a known and easy-to-demonstrate formula:

S = N*(a1+aN)/2

Being N the number of elements, a1 the first element of the sequence and aN the latter. Replacing the values:

S = N*(1 + 2*N-1)/2
  = N²

That is, the sum of the N first odd numbers will be equal to the square of N. In C, a simple program to perform this calculation would be:

int main(void) {

  int N = 20;

  printf("A soma dos %d números ímpares é %d\n", N, N*N);

  return 0;

}

See working on Ideone.

However, the calculation of the product is not as simplified as the sum. Considering only even numbers (and disregarding zero for convenience), the product of the N first even numbers is given by:

P = 2*4*6*...*(2*N)

If we analyze, by definition, all N values are divisible by 2, then we can put them in evidence. In this way, the product is simplified to:

P = 2^N * (1*2*3*...*N)
  = 2^N * N!

That is, to calculate the product of the N first even numbers it is still necessary to calculate the value of N!, that in C it would not be possible (I believe) to escape from a loop of repetition.

#include <math.h>

int main(void) {

  int N = 10;
  int i;
  int fat = 1;

  for (i = 1; i <= N; i++) fat *= i;

  printf("O produto dos %d números pares é %f\n", N, pow(2, N)*fat);

  return 0;

}

see working on Ideone.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.