Doubt about looping loops in C

Asked

Viewed 106 times

1

I’m trying to solve this question:

3. The user enters two numbers x and y (with x < y):
(b) The program returns the sum of the perfect numbers of the range [x, y].

However, he returns the number 2. The test case I’m using is 0 to 10, IE, printf("Item b = %d", q3b(0,10)). Where can I be missing?

int q3b (int x, int y){
    int i, j, somaparcial = 0, somatotal = 0; 

    for (i = x; i <= y; i++){
        for(j = 1; j < i; j++){
            if(i==0 || i%j == 0){
                somaparcial = somaparcial + i;
            }
            
            if( somaparcial == i){
                somatotal = somatotal + i;
            }
        }
    }
    return somatotal;
}

1 answer

5

Superficially looking.

You’re missing that line:

somaparcial = somaparcial + i;

That should be:

somaparcial = somaparcial + j;

And you’re also missing the block:

for (i = x; i <= y; i++){
    for(j = 1; j < i; j++){
        if(i==0 || i%j == 0){
            somaparcial = somaparcial + j;
        }
        
        if( somaparcial == i){
            somatotal = somatotal + i;
        }
    }
}

The variable somaparcial should be reset to each iteration of i:

somaparcial = 0

Where the condition:

if( somaparcial == i){
    somatotal = somatotal + i;
}

A scope should be located above:

for (i = x; i <= y; i++){
    for(j = 1; j < i; j++){
        if(i==0 || i%j == 0){
            somaparcial = somaparcial + j;
        }
    }
    if( somaparcial == i){
        somatotal = somatotal + i;
    }        
}

What applying the corrections to the code presented in the question:

#include <stdio.h>

int q3b (int x, int y){
    int i, j, somaparcial = 0, somatotal = 0; 

    for (i = x; i <= y; i++){
        somaparcial = 0;
        for(j = 1; j < i; j++){
            if(i%j == 0){
                somaparcial = somaparcial + j;
            }
        }
        if(somaparcial == i){
            somatotal = somatotal + i;
        }
    }
    return somatotal;
}

int main(void) {
  printf ("Item b = %d",q3b(0, 10));
}

Test the example on repl it.

A deeper look.

Perfect numbers are natural numbers for which the sum of all its own natural divisors (excluding itself) is equal to the number itself. A OEIS FOUNDATION has in its catalogue a sequence of perfect numbers.

Knowing the perfect number definition and knowing that the problem is to get the sum of all perfect numbers within range so your problem is defined in:

  • iterate for a given range of natural numbers.
  • find the perfect numbers of this range.
  • sum the perfect numbers found.

So to iterate through a range of natural numbers and taking into account the magnitude of the numbers listed in the sequence of perfect numbers, we must ensure the domain whose work will change type of the variables of int and moving on to unsigned long long, i.e., we no longer work with a 32-bit integer whose domain is in the range of [-2147483648, +2147483647] to use a natural 64-bit in whose domain is in the [0, +18446744073709551615] enough to work with the first eight perfect numbers.

It is always good when writing a function to establish safeguards for case the user enters with undue values in the function. In this particular case the provision of the exercise requires that the parameter x is less than the parameter y involving the addition of the safeguard:

if (y < x) return 0;

That is, the function returns 0 if the user does not respect the rule that the parameter x is less than the parameter y.

It is important to use understandable and well-readable names for identifiers. In the specific case I changed the signature of the:

int q3b (int x, int y)

To:

unsigned long long soma_perfeitos(
    unsigned long long inicio,       /* inicio do intervalo de operação da função. */
    unsigned long long fim           /* fim do intervalo de operação da função. */
)

Also clarify variable identifiers and pass your statement within their scope of action.

#include <stdio.h>
/*
 *  A função soma_perfeitos realiza e retorna a soma do
 *  números naturais contidos no intervalo [inicio. fim]
 *  tal que inicio e fim sejam naturais menores que 18446744073709551615
 *  e que inicio anteceda fim.
 */
unsigned long long soma_perfeitos(
    unsigned long long inicio,       /* inicio do intervalo de operação da função. */
    unsigned long long fim           /* fim do intervalo de operação da função. */
){
    if (fim < inicio) return 0;      /* caso o intervalo de operação da função seja contraditório retorna 0. */
    int total = 0;                   /* Inicializa a variável que irá totalizar a soma dos números do números perfeitos */
    for (unsigned long long i = inicio; i <= fim; i++){    /* itera em i pelo intervalo que vai de inicio até fim... */
        int somaDivisores = 0;                             /** ...inicializa a variável que irá guardar a soma dos números de i. **/
        for(unsigned long long j = 1; j < i; j++){         /** ...itera em j pelo intervalo que vai de 1 até i...**/  
            if(i%j == 0){                  /** ... se j for um divisor de i...**/
                somaDivisores += j;        /*** ... soma j a soma dos divisores de i. ***/
            }
        }
        if(somaDivisores == i){            /** ...se i for um número perfeito...**/
            total += i;                    /*** ... adiciona i ao total dos números do números perfeitos. ***/
        }        
    }
    return total;                          /* retorna o resultado da função. */   
}

int main(){
  printf ("Item b = %llu", soma_perfeitos(0,2305));
}

Test the code on Repl.it

Browser other questions tagged

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