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 c, 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);
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.– Maniero
exchange && for ||
– Felipe