47 votes

Comment condenser mes 9 déclarations if en une seule

Je voulais voir quel était le plus petit nombre divisible par tous les nombres à un chiffre et au lieu de le chercher, j'ai créé cela.

 public static void main(String[] args) {

    for (int i = 100; i < 10000; i++) {

        if (i % 2 ==0) {

            if (i % 3 ==0) {

                if (i % 4 ==0) {

                    if (i % 5 ==0) {

                        if (i % 6 ==0) {

                            if (i % 7 ==0) {

                                if (i % 8 ==0) {

                                    if (i % 9 ==0) {

                                        System.out.println(i);

                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
 

Comme vous pouvez le voir, j'ai une instruction if dans une instruction if x9. Le code a fonctionné mais je voulais condenser mes instructions if en utilisant un tableau pour faire ma déclaration if comme ceci mais cela n'a pas fonctionné.

  if (i % x[1, 2, 3, 4, 5, 6, 7, 8]) {
 System.out.println(i);
 break;
 }
 

Aucune suggestion?

153voto

rgettman Points 74908

Au premier abord, on pourrait penser que vous pouvez les tester tous les deux à la fois en plaçant le produit de 2 à 9 sur le côté droit de l' % de l'opérateur.

if (i % (2 * 3 * 4 * 5 * 6 * 7 * 8 * 9) == 0)

Mais parce que certains chiffres incluent les numéros précédents dans leur factorisation, vous devez utiliser un nombre inférieur, plus précisément, le plus petit commun multiple. 8 est un multiple de 2 et de 4, 9 est un multiple de 3, et si 8 et 9 dans le produit, puis 6 (2 * 3) est également pris en compte.

if (i % (5 * 7 * 8 * 9) == 0)

Qui s'avère être 2520, qui est le plus petit commun multiple. Il serait beaucoup plus lisible d'utiliser 2520 et de l'expliquer dans un commentaire pourquoi ce numéro est utilisé.

/**
 * The goal is to test if the number is a multiple of all integers
 * from 2 through 9.  Mathematically, the least common multiple to is a
 * multiple of all its input numbers.  Here, the LCM of 2, 3, ..., 9 is 2520.
 */
public static final int LCM_2_THRU_9 = 2520;

J'ai déclaré une constante et je vais l'utiliser ici:

if (i % LCM_2_THRU_9 == 0)

86voto

saka1029 Points 8764

Essaye ça.

 for (int i = 100; i < 10000; ++i) {
    int x = i;
    if (IntStream.of(2, 3, 4, 5, 6, 7, 8, 9).allMatch(k -> x % k == 0)) {
        System.out.println(i);
        break;
    }
}

-> 2520
 

Ou vous pouvez l'écrire en une seule déclaration.

 int result = IntStream
    .range(100, 10000)
    .filter(i -> IntStream.of(2, 3, 4, 5, 6, 7, 8, 9).allMatch(k -> i % k == 0))
    .findFirst()
    .getAsInt();

System.out.println(result);

-> 2520
 

46voto

stoAlias Points 471

Comme indiqué précédemment, la façon la plus simple d'écrire ce que vous essayez de faire est probablement de rechercher le produit 2 à 9.

Cependant, pour répondre à votre question sur la façon dont vous pouvez condenser les déclarations; les instructions if imbriquées sont équivalentes à l'opérateur logique AND, vous pouvez donc également écrire vos instructions if de la manière suivante:

 if (i % 2 == 0 && i % 3 == 0 && i % 4 == 0 && i % 5 == 0 && i % 6 == 0 && i % 7 == 0 && i % 8 == 0 && i % 9 == 0) {
System.out.println(i);
}
 

43voto

displayName Points 1447

Pourquoi ne pas vous..

Inverser les IFs?


public static void main(String[] args) {

    for (int i = 100; i < 10000; i++) {

        //If value is not valid, continue to next value
        if (i % 2 != 0) continue;
        if (i % 3 != 0) continue;
        if (i % 4 != 0) continue;
        if (i % 5 != 0) continue;
        if (i % 6 != 0) continue;
        if (i % 7 != 0) continue;
        if (i % 8 != 0) continue;
        if (i % 9 != 0) continue;

        //Valid value found. Print and break out of the loop.
        System.out.println(i);
        break;
    }
}

Sinon, le code ci-dessus peut être remaniée en outre à:

public static void main(String[] args) {
    for (int i = 100; i < 10000; i++) {
        if (isPrintable(i)) {
            System.out.println(i);
            break;
        }
    }
}

private static boolean isPrintable(int value) {
    return value % 2 == 0
           && value % 3 == 0
           && value % 4 == 0
           && value % 5 == 0
           && value % 6 == 0
           && value % 7 == 0
           && value % 8 == 0
           && value % 9 == 0;
}

De plus, par @TeePeemm de la suggestion, isPrintable() peut être réduit à:

private static boolean isPrintable(int value) {
    for (int divisor = 2; divisor < 10; divisor++) {
        if (value % divisor != 0) return false;
    }
    return true;
}

1. Il y a de base en langue des raccourcis trop, comme suggéré dans d'autres réponses. Je suis d'accord avec eux.

2. Beaucoup de réponses utilisé le PPCM des nombres pour rendre le code concis, mais c'est un stade de dormance bug d'attente à mordre. L'exécution de la boucle change complètement de ce qui peut être vu en commentant l' break;. Apparemment simple solution présente un subtil, bug potentiel.

20voto

pkpnd Points 5044

Dans Java 8-delà, vous pouvez utiliser un Flux d' approche (en particulier en utilisant IntStream).

Tout d'abord, nous utilisons IntStream.rangeClosed(2, 9) (ou, de manière équivalente, IntStream.range(2, 10)) pour obtenir un flux d'consécutifs Integers en commençant par 2 et se terminant avec l' 9 (inclus). Nous pouvons transformer ce courant en boolean par l'aide d' .allMatch(...), ce qui renvoie true si et seulement si tous les cours d'eau de l'élément correspondant à certains critères. Les critères recherchés sont fournies sous la forme d'une expression lambda, n -> i % n == 0. Cela peut être écrit avec beaucoup de détails comme (Integer n) -> (i % n == 0), de sorte que l'expression lambda prend comme entrée un Integer du ruisseau appelé n, et les rendements s' i (compteur de boucle) est divisible par n. Par conséquent, .allMatch(n -> i % n == 0) retours true si i est divisible par tous les Integer dans le ruisseau.

Nous avons besoin de faire un autre modification: les variables utilisées dans les expressions lambda (comme i) doit être efficacement final:

Une variable ou d'un paramètre dont la valeur n'est jamais changé après c'est initialisée est effectivement final. (La documentation d'Oracle)

Toutefois, le compteur de boucle, i est pas efficace final, puisqu'il est incrémenté (ainsi réaffectés) à chaque itération. La solution est de déclarer une nouvelle variable int x = i; à l'intérieur de la boucle, de sorte qu' x n'est attribué qu'une fois à l'intérieur de son champ d'application (qui est, une itération de la boucle). Par conséquent, x est effectivement finale et peut être utilisé dans l'expression lambda.

Voici la solution finale:

import java.util.stream.IntStream;

public static void main(String[] args) {
    for (int i = 100; i < 10000; i++) {
        int x = i; // x is effectively final
        if (IntStream.rangeClosed(2, 9).allMatch(n -> x % n == 0)) {
            System.out.println(i);
            break;
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X