Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

Dúvida no desafio 4 de números primos

Minha dívida é com relação a esse trecho do código da classe NumerosPrimos:

 public boolean verificarPrimalidade(int numero) {
        if (numero <= 1) {
            return false;
        }
        for (int i = 2; i * i <= numero; i++) {
            if (numero % i == 0) {
                return false;
            }
        }
        return true;
    }

Eu entendi o porque desse código ser escrito na classe NumerosPrimos, que além de facilitar o reaproveitamento e manutenção do código ele só serve para retornar uma verificação de verdadeiro ou falso para que, nesse caso, a classe VerificadorPrimo imprima se é o número é primo ou não, a classe GeradorPrimo imprima o próximo número primo e a própria classe NumerosPrimos imprima só os números primos através do método public void listarPrimos(int limiteSuperior).

Mas eu gostaria de uma explicação do porque nessa verificação booleana o valor 2 volta como true para imprimir a resposta de que é primo?

Eu entendo o funcionamento do 'i * i <= numero, i++', mas fico confuso com o 'numero % i == 0', aqui ele pega o valor atribuído no i = 2 ou o valor do i após os loopings, se o 2 passar por esse calculo do for ele retorna falso por conta da sobra do calculo ser 0?

Então numero 2 passa pelo for ou o código já retorna true após a verificação do if que antecede o for?

Como funciona o calculo do for e a lógica aplicada?

Realmente eu não estou conseguindo entender esse funcionamento.

6 respostas

Assim, posso dar o exemplo do número 7. O for vai começar i = 2, ai ele vai dar false no if pq 7 % 2 = 1, ai segundo loop i = 4, false no if pq 7 % 4 = 3, só que agora, no terceiro for o i é igual a 8, entao o loop quebra pois 8 > 7, ai no fim vai retornar true. Finalizando, a ideia do i * i é para agilizar o código.

Obrigado pela reposta Arthur.

Pelo que entendi então, utilizando o i * i, com esse exemplo do 7 ficaria assim, visto que o int i = 2 está dando um valor inicial para i, o i * i <= numero é a condição de verificação para o loop e o i++ é o que fazer a cada repetição.

Então temos: 2 * 2 = 4, como 4 <= 7, roda o 7 % 2 = 1, como 1 não é == 0 ele repete o loop acrescentando 1 no i por conta do i++, e seguiria para 3 * 3 = 9, como 9 > 7 quebra o loop e retorna o true. O que faz com que qualquer numero par na primeira checagem já retorne 0 e qualquer numero ímpar retorne 1. OK

E em vez de 7, for 2, o loop já quebraria na primeira verificação, por conta de 4 > 2 e por isso retorna true?

Mas em casos como o sendo o 9 no lugar do 7, na segunda repetição retornaria false, visto que a condição ficaria 3 * 3 = 9 e como 9 se enquadra em <= o numero que seria 9, o loop continua e vai para 9 % 3 = 0 retornando o false e parando o loop.

Como observei, sendo i * i <= numero, ele retorna o 9 como false, ou seja não sendo primo.

Se colocar i * i < numero o 9 retorna como true mas o 4 também retorna como true.

O que se percebe ao rodar a linha para criar uma lista de números primos ou a para verificar se o número é primo.

Esse loop está com erro de lógica e retorna erro.

Para resolver esse problema e manter o código ágil, visto que exceto pelo número 2, todo número primo quando dividido por 2 sobra/retorna 1 e todo número não primo quando dividido por 2 sobra/retorna 0, fiz assim.

public boolean verificarPrimalidade(int numero) {
        if (numero <= 1) {
            return false;
        } else if (numero == 2) {
            return true;
        } else if (numero % 2 == 0) {
            return false;
        } else {
            return true;
        }
    }
solução!

Perdão por ter escrito errado na minha resposta, não sei pq pensei que o i encrementava + 2, mas mesmo assim, a lógica é a mesma, 2 * 2 <= 7 passa o for e 3 * 3 <= 7 eh verdadeiro então o loop não se inicia. "Se colocar i * i < numero o 9 retorna como true mas o 4 também retorna como true.". O loop não está com erro de lógica, e sim de como está escrito, como vc havia escrito no primeiro post, o for esta assim for (int i = 2; i * i <= numero; i++) { só que agora, vc ta colocando apenas i * i < numero, entao, troque para i * i <= numero. Finalizando, o código que voce mandou no terceiro post é falho, por se o numero for igual a 9, ele daria como true, e 9 não é primo.

public static void main(String[] args) {
        System.out.println(verificarPrimalidade(2));
    }
    public static boolean verificarPrimalidade(int numero) {
        if (numero <= 1) {
            return false;
        }
        for (int i = 2; i * i <= numero; i++) {
            if (numero % i == 0) {
                return false;
            }
        }
        return true;
    }

no terminal eu recebi true testando com o número 2, pois 2 * 2 é maior que dois então nem iniciou o loop, sendo assim retornando true

Você está certo Arthur.

Com a sua primeira explicação consegui entender o código, meu erro foi a confusão que fiz em achar que o 9 era um número primo e por isso acabei errando.

Obrigado pela atenção dada, correções e respostas.

Eu que sou grato por ter conseguido ajudar Rodrigo, até eu me confundo as vezes, faz parte, o importante eh o aprendizado. Boa sorte nos estudos!