104 votes

Déterminer si un nombre est un multiple de dix ou s'il est compris dans un ensemble particulier d'intervalles.

J'ai besoin de quelques boucles dans mon programme. Je peux écrire le pseudo-code, mais je ne sais pas vraiment comment les écrire logiquement.

J'ai besoin

if (num is a multiple of 10) { do this }

if (num is within 11-20, 31-40, 51-60, 71-80, 91-100) { do this }
else { do this } //this part is for 1-10, 21-30, 41-50, 61-70, 81-90

Il s'agit d'un jeu de société "Serpents et échelles", si ma question a plus de sens.

J'imagine que le premier si Je vais devoir utiliser le module. Est-ce que if (num == 100%10) être correct ?

Le second, je n'en ai aucune idée. Je peux l'écrire comme if (num > 10 && num is < 21 || etc.) mais il doit y avoir quelque chose de plus intelligent que ça.

17 votes

En général, la longueur d'un bon code est proportionnelle à la longueur de l'anglais décrivant ce qu'il fait. Ainsi, lorsque votre "spécification" indique 11-20, 31-40, 51-60, 71-80, 91-100, vous pouvez vous attendre à ce que votre code mentionne également ces chiffres. Si ces chiffres proviennent de quelque part ou ont été générés par une raison quelconque, voyez si vous pouvez coder la raison plutôt que les chiffres.

40 votes

@user3419168 : Le compilateur ne se soucie guère de la lisibilité de votre code ; il le compilera en une fraction de seconde. Mais pour les humains qui lisent votre code, les choix que vous faites peuvent faire en sorte qu'il soit compris en quelques secondes, minutes, heures, ou jamais. Cela a un coût ; les gens sont payés pour lire et comprendre le code, alors facilitez-leur la tâche. Rédigez toujours le code de production de manière à maximiser sa lisibilité et n'oubliez pas que la concision ne rend pas nécessairement le code plus performant.

0 votes

Les titres de vos deux autres questions sont de très bons titres ; ils décrivent précisément le sujet technique de la question. J'ai édité celui-ci parce qu'il était vague, et concernait plus votre personne que le problème de codage.

89voto

Winston Ewert Points 17746

Pour le premier, pour vérifier si un nombre est un multiple de l'utilisation :

if (num % 10 == 0) // It's divisible by 10

Pour le second :

if(((num - 1) / 10) % 2 == 1 && num <= 100)

Mais c'est plutôt dense, et vous feriez mieux de simplement énumérer les options de manière explicite.


Maintenant que vous avez donné une meilleure idée de ce que vous faites, j'écrirais le deuxième comme :

   int getRow(int num) {
      return (num - 1) / 10;
   }

   if (getRow(num) % 2 == 0) {
   }

C'est la même logique, mais en utilisant la fonction, nous avons une idée plus claire de ce qu'elle signifie.

80 votes

if((num - 1) / 10) % 2 == 1 && num < 100) - Je pleurerais si je voyais ça.

32 votes

@DanielKamilKozar, comme vous le devriez.

0 votes

Une dernière chose : désolé de pinailler, mais ça devrait être num <= 100 pour inclure 100 (ou de la manière dont il serait écrit en c++).

40voto

Adam Liss Points 27815

si (num est un multiple de 10) { faire ceci }

if (num % 10 == 0) {
  // Do something
}

si (num est dans 11-20, 31-40, 51-60, 71-80, 91-100) { faire ceci }

L'astuce consiste à rechercher une sorte de point commun entre les gammes. Bien sûr, vous pouvez toujours utiliser la méthode de la "force brute" :

if ((num > 10 && num <= 20) ||
    (num > 30 && num <= 40) ||
    (num > 50 && num <= 60) ||
    (num > 70 && num <= 80) ||
    (num > 90 && num <= 100)) {
  // Do something
}

Mais vous pourriez remarquer que, si vous soustrayez 1 de num vous aurez les gammes :

10-19, 30-39, 50-59, 70-79, 90-99

En d'autres termes, tous les nombres à deux chiffres dont le premier chiffre est impair. Ensuite, vous devez trouver une formule pour exprimer cela. Vous pouvez obtenir le premier chiffre en divisant par 10, et vous pouvez vérifier qu'il est impair en vérifiant que le reste est égal à 1 lorsque vous divisez par 2. En mettant tout ça ensemble :

if ((num > 0) && (num <= 100) && (((num - 1) / 10) % 2 == 1)) {
  // Do something
}

Étant donné le compromis entre un code plus long mais maintenable et un code plus court et "intelligent", je choisirais toujours un code plus long et plus clair. Au minimum, si vous essayez d'être intelligent, veuillez inclure un commentaire qui explique exactement ce que vous essayez d'accomplir.

Il est utile de supposer que le prochain développeur qui travaillera sur le code est armé et sait où vous vivez. :-)

7 votes

J'opterais toujours pour le code intelligent, mais je le transformerais en code facile à maintenir en extrayant les fonctions. Ce serait tout aussi lisible si la dernière partie disait && isTensDigitOdd(num) Il est possible d'ajouter un commentaire avant la définition de la fonction pour expliquer ce qu'elle fait. Si un tel modèle existe, un commentaire expliquant le raisonnement pour le modèle est éclairant pour la maintenabilité, je pense.

3 votes

Chris, c'est une excellente stratégie lorsque l'"intelligence" présente un avantage clair : un code beaucoup plus court (ce qui signifie moins de risques de fautes de frappe, surtout s'il est modifié), ou une amélioration importante de l'efficacité. Il y a presque toujours un compromis entre la brièveté, la clarté et l'efficacité, et trouver un bon compromis est une excellente compétence à développer. (Voir stackoverflow.com/a/2151844/29157 pour un ricanement.)

1 votes

C'est une bien meilleure approche. Elle est beaucoup plus facile à comprendre que le "code intelligent" et la différence de performance est probablement négligeable.

30voto

Bryan Chen Points 14689

Si vous utilisez GCC ou tout autre compilateur qui supporte gammes de cas vous pouvez le faire, mais votre code ne pas être portable .

switch(num)
{
case 11 ... 20:
case 31 ... 40:
case 51 ... 60:
case 71 ... 80:
case 91 ... 100:
    // Do something
    break;
default:
    // Do something else
    break;
}

1 votes

Pouvez-vous me dire pourquoi ce code n'est pas portable ?

8 votes

@MSharathHegde parce que cela nécessite une extension GCC, qui ne fait pas partie de la norme et certains compilateurs ne la supportent pas.

5 votes

C'est la bonne réponse, car l'intention est immédiatement apparente. Toutes ces réponses "intelligentes" avec modulo sont un cauchemar de maintenance, même avec des commentaires.

15voto

chris Points 28950

Ceci s'adresse davantage aux futurs visiteurs qu'aux débutants. Pour une solution plus générale, de type algorithmique, vous pouvez prendre une liste de valeurs de début et de fin et vérifier si une valeur passée est comprise dans l'une d'entre elles :

template<typename It, typename Elem>
bool in_any_interval(It first, It last, const Elem &val) {
    return std::any_of(first, last, [&val](const auto &p) {
        return p.first <= val && val <= p.second;
    });
}

Pour simplifier, j'ai utilisé un lambda polymorphe (C++14) au lieu d'un explicite pair argument. Il faudrait aussi s'en tenir à l'utilisation de < et == pour être cohérent avec les algorithmes standards, mais cela fonctionne ainsi tant que Elem a <= défini pour elle. Quoi qu'il en soit, il peut être utilisé comme suit :

std::pair<int, int> intervals[]{
    {11, 20}, {31, 40}, {51, 60}, {71, 80}, {91, 100}
};

const int num = 15;
std::cout << in_any_interval(std::begin(intervals), std::end(intervals), num);

Voici un exemple concret ici .

0 votes

Une solution astucieuse. J'aurais probablement utilisé un tableau unique, puisque vous pouvez le formater avec 2 chiffres par ligne pour représenter les paires.

0 votes

@HunterGuy2, Très bon point. Je vais en fait le changer pour qu'il opère sur des paires parce que je ne pensais qu'aux itérateurs zip pour une raison quelconque.

0 votes

Très belle approche stl ! Je l'adore !

5voto

La-comadreja Points 3057

Avec quelques bons commentaires dans le code, il peut être écrit de manière assez concise et lisible.

// Check if it's a multiple of 10
if (num % 10 == 0) { ... }

// Check for whether tens digit is zero or even (1-10, 21-30, ...)
if ((num / 10) % 2 == 0) { ... }
else { ... }

2 votes

Le premier commentaire est inutile. Tout programmeur ayant un peu d'expérience sait que num % 10 == 0 est la même chose que num est un multiple de 10.

7 votes

Oui, mais les débutants lisent aussi ce site. Je n'utiliserais normalement pas ce commentaire dans mon propre code, mais il rend la réponse plus claire pour les débutants qui pourraient bénéficier de cette question de débutant.

2 votes

Ne faites jamais cela. Cela réduit en fait la lisibilité, en ralentissant le lecteur et en l'obligeant à tout lire deux fois. Tout programmeur qui ne comprend pas que if (num % 10 == 0) signifie la même chose que // Check if it's a multiple of 10 ne devrait pas être maintenu votre code. Il s'agit d'un anti-modèle bien connu.

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