J'ai expliqué à mes élèves que le test égal à n'est pas fiable pour les variables flottantes, mais convient pour les entiers. Le manuel que j'utilise dit qu'il est plus facile de lire> et <que> = et <=. Je suis d'accord dans une certaine mesure, mais dans une boucle For? N'est-il pas plus clair que la boucle spécifie les valeurs de début et de fin?
Suis-je en train de manquer quelque chose dont l'auteur du manuel a raison?
Un autre exemple est dans les tests de gamme comme:
si score> 89 grade = 'A'
sinon si score> 79 grade = 'B' ...
Pourquoi ne pas simplement dire: si score> = 90?
Réponses:
Dans les langages de programmation à accolades avec des tableaux à base zéro , il est habituel d'écrire des
for
boucles comme ceci:Cela traverse tous les éléments du tableau et est de loin le cas le plus courant. Il évite l'utilisation de
<=
ou>=
.La seule fois que cela devrait changer, c'est quand vous devez ignorer le premier ou le dernier élément, ou le traverser dans la direction opposée, ou le traverser depuis un point de départ différent ou vers un point d'arrivée différent.
Pour les collections, dans les langues qui prennent en charge les itérateurs, il est plus courant de voir ceci:
Ce qui évite complètement les comparaisons.
Si vous cherchez une règle stricte et rapide quant à l'utilisation de
<=
vs<
, il n'y en a pas; utilisez ce qui exprime le mieux votre intention. Si votre code doit exprimer le concept «inférieur ou égal à 55 miles par heure», il doit dire<=
non<
.Répondre à votre question sur les gammes de notes est
>= 90
plus logique, car 90 est la valeur limite réelle, pas 89.la source
for
boucles comme celle-ci. La forme defor
boucle que j'ai fournie ici sera instantanément reconnaissable par tout développeur ayant un minimum d'expérience. Si vous voulez une réponse plus spécifique basée sur un scénario plus spécifique, vous devez l'inclure dans votre question.Ça n'a pas d'importance.
Mais pour le bien de l'argument, nous allons analyser les deux options:
a > b
vsa >= b
.Attendre! Ce ne sont pas équivalents!
OK, puis
a >= b -1
vsa > b
oua > b
vsa >= b +1
.Hm,
a >b
et lesa >= b
deux sont meilleurs quea >= b - 1
eta >= b +1
. Quels sont tous ces1
s de toute façon? Je dirais donc que tout avantage d'avoir à la>
place>=
ou vice-versa est éliminé en devant ajouter ou soustraire des1
s aléatoires .Et si c'est un chiffre? Vaut-il mieux dire
a > 7
oua >= 6
? Attends une seconde. Sommes-nous sérieusement en train de nous demander s'il est préférable d'utiliser>
vs>=
et d'ignorer les variables codées en dur? Donc, cela devient vraiment une question de savoir sia > DAYS_OF_WEEK
c'est mieux quea >= DAYS_OF_WEEK_MINUS_ONE
... ou est-cea > NUMBER_OF_LEGS_IN_INSECT_PLUS_ONE
vsa >= NUMBER_OF_LEGS_IN_INSECT
? Et nous revenons à l'ajout / la soustraction de1
s, mais cette fois dans les noms de variables. Ou peut-être débattre s'il est préférable d'utiliser le seuil, la limite, le maximum.Et il semble qu'il n'y ait pas de règle générale: cela dépend de ce qui est comparé
Mais vraiment, il y a des choses beaucoup plus importantes à améliorer dans son code et des directives beaucoup plus objectives et raisonnables (par exemple, la limite de caractères X par ligne) qui ont encore des exceptions.
la source
>
vs>=
ou de la question de savoir si la discussion de>
vs>=
est significative? bien qu'il soit probablement préférable d'éviter d'en discuter: pCalculativement, il n'y a pas de différence de coût lors de l'utilisation
<
ou>
par rapport à<=
ou>=
. Il est calculé aussi rapidement.Cependant, la plupart des boucles compteront à partir de 0 (car de nombreuses langues utilisent l'indexation 0 pour leurs tableaux). Donc, la boucle canonique pour dans ces langues est
faire cela avec un
<=
vous obligerait à ajouter un -1 quelque part pour éviter l'erreur off-by oneou
Bien sûr, si le langage utilise une indexation basée sur 1, vous utiliserez <= comme condition limite.
La clé est que les valeurs exprimées dans la condition sont celles de la description du problème. C'est plus propre à lire
pour un intervalle semi-ouvert que
et doivent faire le calcul pour savoir qu'il n'y a pas de valeur possible entre 19 et 20
la source
for(markup = 5; markup <= MAX_MARKUP; ++markup)
. Tout le reste serait trop compliqué.Je dirais que le point n'est pas de savoir si vous devez utiliser> ou> =. Le but est d'utiliser tout ce qui vous permet d'écrire du code expressif.
Si vous trouvez que vous devez ajouter / soustraire un, envisagez d'utiliser l'autre opérateur. Je trouve que de bonnes choses se produisent lorsque vous commencez avec un bon modèle de votre domaine. Ensuite, la logique s'écrit.
C'est beaucoup plus expressif que
Dans d'autres cas, l'autre voie est préférable:
Beaucoup mieux que
Veuillez excuser "l'obsession primitive". Évidemment, vous voudriez utiliser respectivement un type Velocity et Money, mais je les ai omis pour des raisons de concision. Le point est le suivant: utilisez une version plus concise et qui vous permet de vous concentrer sur le problème commercial que vous souhaitez résoudre.
la source
Comme vous l'avez souligné dans votre question, le test d'égalité sur les variables flottantes n'est pas fiable.
Il en va de même pour
<=
et>=
.Cependant, il n'y a pas un tel problème de fiabilité pour les types entiers. À mon avis, l'auteur exprimait son opinion sur ce qui est plus lisible.
Que vous soyez d'accord ou non avec lui, c'est bien sûr votre opinion.
la source
<
ou en<=
fonction de ce qui est le plus naturel pour le problème particulier que je résous. Comme d'autres l'ont souligné, une boucle FOR a<
plus de sens dans les langages de type C. Il existe d'autres cas d'utilisation qui favorisent<=
. Utilisez tous les outils à votre disposition, quand et où cela est approprié.for (unsigned int i = n; i >= 0; i--)
oufor (unsigned int i = x; i <= y; i++)
siy
cela se produitUINT_MAX
. Oups, ces boucles pour toujours.Chacune des relations
<
,<=
,>=
,>
et aussi==
et!=
ont leur cas d' utilisation pour comparer deux valeurs à virgule flottante. Chacun a un sens spécifique et celui qui convient doit être choisi.Je vais donner des exemples de cas où vous voulez exactement cet opérateur pour chacun d'eux. (Soyez conscient des NaN, cependant.)
f
qui prend en entrée une valeur à virgule flottante. Afin d'accélérer vos calculs, vous décidez d'ajouter un cache des valeurs les plus récemment calculées, qui est, un mappage de table de recherchex
pourf(x)
. Vous aurez vraiment besoin d'utiliser==
pour comparer les arguments.x
? Vous voulez probablement utiliserx != 0.0
.x
est dans l'intervalle unitaire?(x >= 0.0) && (x < 1.0)
est la bonne condition.d
d'une matrice et vous voulez savoir s'il est défini positif? Il n'y a aucune raison d'utiliser autre chose qued > 0.0
.alpha <= 1.0
.Les mathématiques à virgule flottante (en général) ne sont pas exactes. Mais cela ne signifie pas que vous devez le craindre, le traiter comme de la magie et certainement pas toujours traiter deux quantités à virgule flottante égales si elles sont à l'intérieur
1.0E-10
. Cela cassera vraiment vos calculs et provoquera toutes les choses étranges.x != 0.0
ety
est une valeur à virgule flottante finie, ily / x
n'est pas nécessaire qu'elle soit finie. Mais il pourrait être pertinent de savoir si cey / x
n'est pas fini à cause d'un débordement ou parce que l'opération n'était pas mathématiquement bien définie pour commencer.x
doit être dans l'intervalle unitaire [0, 1), je serais vraiment contrarié s'il tirait un échec d'assertion lorsqu'il était appelé avecx == 0.0
oux == 1.0 - 1.0E-14
.1.0E-30
, rien n'est gagné. Tout ce que vous avez fait, c'est augmenter la probabilité de donner la mauvaise réponse.alpha
peut être affecté par des erreurs d'arrondi etalpha <= 1.0
peut donc être vrai même si la véritable valeur mathématique de l'expression aalpha
été calculée à partir de peut-être était vraiment supérieure à 1. Mais vous ne pouvez rien faire à ce stade.Comme toujours en génie logiciel, traitez les erreurs au niveau approprié et ne les gérez qu'une seule fois. Si vous ajoutez des erreurs d'arrondi dans l'ordre de
1.0E-10
(cela semble être la valeur magique que la plupart des gens utilisent, je ne sais pas pourquoi) chaque fois que vous comparez des quantités à virgule flottante, vous serez bientôt en erreur dans l'ordre de1.0E+10
…la source
Le type de conditionnel utilisé dans une boucle peut limiter les types d'optimisations qu'un compilateur peut effectuer, pour le meilleur ou pour le pire. Par exemple, étant donné:
un compilateur pourrait supposer que la condition ci-dessus devrait entraîner la sortie de la boucle après la nième boucle de passage, à moins que n ne puisse 65535 et que la boucle puisse se terminer d'une autre manière que si i dépasse n. Si ces conditions s'appliquent, le compilateur doit générer du code qui entraînerait l'exécution de la boucle jusqu'à ce que quelque chose d'autre que la condition ci-dessus provoque sa fermeture.
Si la boucle avait plutôt été écrite comme suit:
alors un compilateur pourrait supposer en toute sécurité que la boucle n'aurait jamais besoin de s'exécuter plus de n fois et pourrait ainsi générer du code plus efficace.
Notez que tout débordement avec des types signés peut avoir des conséquences désagréables. Donné:
Un compilateur pourrait réécrire cela comme:
Une telle boucle se comporterait de manière identique à l'original si aucun débordement ne se produit dans les calculs, mais pourrait s'exécuter indéfiniment, même sur les plates-formes matérielles où le débordement d'entier aurait normalement une sémantique d'encapsulation cohérente.
la source