J'ai ce code affreux :
if ( v > 10 ) size = 6;
if ( v > 22 ) size = 5;
if ( v > 51 ) size = 4;
if ( v > 68 ) size = 3;
if ( v > 117 ) size = 2;
if ( v > 145 ) size = 1;
return size;
Comment puis-je me débarrasser des multiples instructions if ?
J'ai ce code affreux :
if ( v > 10 ) size = 6;
if ( v > 22 ) size = 5;
if ( v > 51 ) size = 4;
if ( v > 68 ) size = 3;
if ( v > 117 ) size = 2;
if ( v > 145 ) size = 1;
return size;
Comment puis-je me débarrasser des multiples instructions if ?
Que diriez-vous d'une telle approche :
int getSize(int v) {
int[] thresholds = {145, 117, 68, 51, 22, 10};
for (int i = 0; i < thresholds.length; i++) {
if (v > thresholds[i]) return i+1;
}
return 1;
}
Fonctionnellement : (Démontré en Scala)
def getSize(v: Int): Int = {
val thresholds = Vector(145, 117, 68, 51, 22, 10)
thresholds.zipWithIndex.find(v > _._1).map(_._2).getOrElse(0) + 1
}
L'avantage de cette approche est qu'elle peut être facilement étendue à d'autres étapes ou à une gamme plus large sans grand effort.
Si vous laissez les clés comme l'a fait le PO, vous pouvez utiliser lowerEntry au lieu de floorEntry. De cette façon, les données sont cohérentes avec l'OP.
Le problème le plus évident avec la solution du PO est la ramification, je suggérerais donc une régression polynomiale. Cela donnera une belle expression sans branchements de la forme
size = round(k_0 + k_1 * v + k_2 * v^2 + ...)
Bien sûr, vous n'obtiendrez pas un résultat exact, mais si vous pouvez tolérer une certaine déviance, c'est une alternative très performante. Puisque le comportement "non modifié" de la fonction originale pour les valeurs où v<10
est impossible à modéliser avec un polynôme, j'ai pris la liberté de supposer une interpolation de retenue d'ordre zéro pour cette région.
Pour un polynôme de 45 degrés avec les coefficients suivants,
-9.1504e-91 1.1986e-87 -5.8366e-85 1.1130e-82 -2.8724e-81 3.3401e-78 -3.3185e-75 9.4624e-73 -1.1591e-70 4.1474e-69 3.7433e-67 2.2460e-65 -6.2386e-62 2.9843e-59 -7.7533e-57 7.7714e-55 1.1791e-52 -2.2370e-50 -4.7642e-48 3.3892e-46 3.8656e-43 -6.0030e-41 9.4243e-41 -1.9050e-36 8.3042e-34 -6.2687e-32 -1.6659e-29 3.0013e-27 1.5633e-25 -8.7156e-23 6.3913e-21 1.0435e-18 -3.0354e-16 3.8195e-14 -3.1282e-12 1.8382e-10 -8.0482e-09 2.6660e-07 -6.6944e-06 1.2605e-04 -1.7321e-03 1.6538e-02 -1.0173e-01 8.3042e-34 -6.2687e-32 -1.6659e-29 3.0013e-27 1.5633e-25 -8.7156e-23 6.3913e-21 1.0435e-18 -3.0354e-16 3.8195e-14 -3.1282e-12 1.8382e-10 -8.0482e-09 2.6660e-07 -6.6944e-06 1.2605e-04 -1.7321e-03 1.6538e-02 -1.0173e-01 3.6100e-01 -6.2117e-01 6.3657e+00
vous obtenez une courbe magnifiquement ajustée :
Et comme vous pouvez le voir, vous obtenez une erreur à la norme 1 de seulement 1,73 sur toute la gamme de 0 à 200* !
*Résultats pour v[0,200]
peut varier.
J'adore cela car j'ai toujours aimé trouver des expressions qui "emballent" les données d'une recherche dans des expressions mathématiques. Prenez quelques constantes, ajoutez quelques multiplications, additions, modulus, abs(), floor(), etc., et vous pouvez faire des choses amusantes pour calculer des choses comme le nombre de jours de chaque mois. Mais je n'ai jamais pensé à un polynôme pour ce genre de choses !
Wow ! Pourriez-vous nous en dire plus sur les outils que vous avez utilisés pour produire ce résultat ?
if ( v > 145 ) size = 1;
else if ( v > 117 ) size = 2;
else if ( v > 68 ) size = 3;
else if ( v > 51 ) size = 4;
else if ( v > 22 ) size = 5;
else if ( v > 10 ) size = 6;
return size;
C'est mieux pour votre cas.
En option, vous devriez choisir le Switch Case dans la mesure du possible.
Update:
Si vous avez analysé que la valeur de 'v' se situe généralement dans une plage inférieure (<10) dans la plupart des cas, vous pouvez ajouter ceci.
if(v < 10) size = SOME_DEFAULT_VALUE;
else if ( v > 145 ) size = 1;
else if ( v > 117 ) size = 2;
else if ( v > 68 ) size = 3;
else if ( v > 51 ) size = 4;
else if ( v > 22 ) size = 5;
else if ( v > 10 ) size = 6;
further :
Vous pouvez également modifier la séquence des conditions, en fonction de votre analyse. Si vous savez que la plupart des valeurs sont inférieures à 10 et qu'en second lieu, la plupart des valeurs se situent entre 68 et 117, vous pouvez modifier la séquence de conditions en conséquence.
Edits :
if(v < 10) return SOME_DEFAULT_VALUE;
else if ( v > 145 ) return 1;
else if ( v > 117 ) return 2;
else if ( v > 68 ) return 3;
else if ( v > 51 ) return 4;
else if ( v > 22 ) return 5;
else if ( v > 10 ) return 6;
@NimChimpsky Ce serait plus readable
. Je ne dis pas qu'il est meilleur en termes de performances, cela dépend de nombreux facteurs.
Encore mieux : il suffit de renvoyer la valeur tout de suite sans utiliser les intermédiaires. size
variable.
Vous êtes sérieux ? C'est beaucoup plus illisible, et ce n'est pas facile à changer si les règles de "taille" changent.
Pourriez-vous lire la question initiale ? "Comment puis-je me débarrasser des multiples instructions if ?" Comme vous pouvez le constater, il n'y a pas d'instructions "if" dans ma réponse.
@gasan, bien sûr, vous avez supprimé le if's
mais l'opérateur a affirmé que son code était ugly
et destiné à le rendre plus lisible... vous croyez vraiment que c'est... plus joli ?
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.
4 votes
Tu voulais vraiment que les numéros 5 et 6 soient dans cet ordre ?
1 votes
Non, je ne l'ai pas fait, mon erreur.
62 votes
Pour info, je ne pense pas que ce soit particulièrement laid. Il est facile de voir ce qui se passe, il est trivial d'ajouter d'autres cas, c'est clair. La seule chose que j'envisagerais de faire est d'ajouter une liste où les conditions/valeurs sont stockées, mais à part ça, je n'ai aucun problème avec ça.
0 votes
Toutes ces réponses et personne n'a choisi une déclaration d'interrupteur, qui est clairement mieux adaptée à cette situation.
3 votes
Comment cela ? Ce n'est pas une comparaison "==".
13 votes
Ce code n'est pas laid ! Une solution plus "fantaisiste" ne fera que rendre votre code plus illisible et plus difficile à maintenir à l'avenir.
7 votes
@Stephen : Je ne vois pas pourquoi un switch avec 145 cas est moins laid. Regardez de plus près, un
>
est utilisé comme équation, et non==
.1 votes
Alors que fait le code si v <= 10 ?
3 votes
Vous ne mentionnez pas où vous avez besoin de ce type de code. Tous ces chiffres magiques me font me demander où ils sont utilisés.
0 votes
Cette question est liée au WTF quotidien (d'où un grand nombre de vues) : forums.thedailywtf.com/forums/p/20192/234306.aspx On a là-bas suggéré une
switch
à l'intérieur d'unwhile
ce qui n'a pas été répondu auparavant dans ce sujet. Je ne suis pas sûr de l'apprécier plus que l'opérateur ternaire. Elle est aussi moins efficace.0 votes
Le commutateur à l'intérieur du while est une énorme surcharge (oui je sais, je devrais être en train de parler). La comparaison est la meilleure solution, quelle que soit la façon dont vous la faites. Mais imaginez le gaspillage de cycles pour une boucle si les nombres étaient plus éloignés.
2 votes
Pour ceux qui seraient tentés de prendre au sérieux le concept de boucle et de commutateur c'est une blague ! C'est l'un des gags classiques de DailyWTF, comme
enum BOOL { TRUE, FALSE, FILE_NOT_FOUND };
. (Oui, je sais, expliquer la blague est nul. Mais je ne veux pas maintenir le code d'un pauvre type qui l'a prise au sérieux).3 votes
Ce qui est laid dans ce code, c'est l'utilisation de chiffres magiques et de constantes codées en dur. À mes yeux, les multiples IF ne sont pas un problème, ils sont simples, efficaces et lisibles, mais ce sont les valeurs constantes qui sont illisibles...
3 votes
Cette question a suscité un grand nombre de réponses créatives qui sont toutes des idées vraiment mauvaises dans la programmation de la vie réelle ...
20 votes
Tant de votes positifs pour une réponse aussi simple à une question simple, alors que les questions et réponses difficiles ne sont pas autant votées. StackOverflow est-il dysfonctionnel ?
0 votes
@Chris j'apprécie votre commentaire, mais c'est le souhait et le goût des autres ce qu'ils veulent faire.
0 votes
LECTURE sur la construction if..then..else en Java( !?) Cette question est l'exemple parfait de fournir un morceau de code comme exemple et de réussir quand même à faire un non-constructif/controversé/hors-sujet. Si vous n'aimez pas if..then..else - faites votre propre développement DSL, si vous ne connaissez pas l'existence du switch .... Je suppose - apprenez les mots-clés Java. Je ne peux aider que par le downvoting
0 votes
En y réfléchissant bien, cette question a sa propre façon de stimuler la créativité un effet très étrange et inhabituel (un concours de codage sur un problème sans queue ni tête). Pourquoi ne pas étiqueter cette question comme "laide" ?