Y a-t-il un moyen de supprimer l'instruction IF-IF suivante pour vérifier si la valeur est inférieure à 0? La valeur de Nous faisons ce J'ai été habitué à Python Modulo Opérateur d'utiliser la signature du diviseur où notre compilateur (C89) utilise la signature de dividendes. P> est là un moyen de faire ce calcul différemment?
Exemple de résultats: P> C code> devrait mentir entre 0 et 3600. Les deux
A code> et
B code> sont signés. La valeur du
A code> doit également se situer entre 0 et 3600. (Oui, il s'agit d'une valeur de comptage dans 0,1 degrés). La valeur est réinitialisée par une interruption à 3600, mais si cette interruption est trop tardive, elle ne pose pas de problème, mais le logiciel doit toujours être en mesure de le gérer. Ce qu'il fait. P>
si (C Vérifiez à des endroits assez certains où nous calculons des positions. (Calculer une nouvelle position, etc.) P>
a - b = c
100 - 200 = 3500
200 - 100 = 100
5 Réponses :
Pourquoi êtes-vous inquiet pour la branche? [raison expliquée dans les commentaires à la question.] em> L'alternative est quelque chose comme: p> Ceci suppose A code > et
b code> sont dans la plage
0..3600 code> déjà; S'ils ne sont pas sous contrôle, la solution plus générale est celle de Drew McGowen Suggest : P>
((a - b) % 3600 + 3600) % 3600
bonne question! Que dis-tu de ça?
c += 3600 * (c < 0);
@Abelenky Non, les valeurs de vérité sont zéro / non nulle, mais les opérateurs de comparaison ne renvoient que zéro ou un.
@skjaidev a montré comment le faire sans ramification. Voici comment éviter automatiquement la multiplication, aussi bien lorsque INT code> S est TwoS-Complément:
#if ((3600 & -0) == 0) && ((3600 & -1) == 3600)
c += 3600 & -(c < 0);
#else
c += 3600 * (c < 0);
#endif
Qu'en est-il de cela (en supposant des INT de 32 bits): La droite du numéro de numéro négatif est formellement définie par la mise en oeuvre conformément aux documents standard de C, mais il est presque toujours mis en œuvre avec la copie du MSB (les processeurs courants peuvent le faire dans une seule instruction. ). P> Cela n'entraînera certainement aucune branche, contrairement à c >> 31 code> définit tous les bits sur le MSB d'origine, qui est 1 pour les nombres négatifs et et 0 pour d'autres personnes en 2-complément. p>
(C <0) code> qui pourrait être mis en œuvre avec une branche dans certains cas. P> P>
Très agréable. Mais vous devriez annuler (C >> 31) avant de l'ajouter à 3600.
@ Sát Non, je veux avoir un masque complet si le nombre est négatif (MSB est 1). Je veux zéro si le nombre est non négatif.
Euh, assez vrai, désolé pour ça: $.
Pour les entiers signés, il est défini la mise en œuvre de savoir si vous obtiendrez le bit de signalisation répliqué. ISO / IEC 9899: 2011 §6.5.7 Opérateurs de décalage des bits: ¶5 Le résultat de E1 >> E2 code> est
E1 code> droite décalé
E2 code> E2 code> Positions de bits. Si
E1 code> a un type non signé ou si
E1 code> a un type signé et une valeur non négative, la valeur du résultat fait partie intégrante du quotient de
E1 / 2 ** e2 code> [exponentiation; ne peut pas faire de superscripts dans les commentaires] i>. Si
E1 code> a un type signé et une valeur négative, la valeur résultante est définie par la mise en œuvre.
Bien qu'une belle solution, cela n'est tristement pas autorisé selon nos malaques que nous devons nous conformer. Il est possible de le rendre conforme mais entraîne de nombreuses moulages laids.
Ce que vous voulez faire est l'arithmétique modulaire. Votre machine de complément de 2 est déjà en integer Math. Donc, en mappant vos valeurs dans le complément de 2 arithmétiques, vous pouvez obtenir le fonctionnement Modolo gratuitement.
Le truc est de représenter votre angle comme une fraction de 360 degrés compris entre 0 et 1-Epsilon. Bien sûr, alors vos angles constants devraient être représentés de la même manière, mais cela ne devrait pas être difficile; c'est juste un peu de mathématiques que nous pouvons nous cacher dans une fonction de conversion (ER, macro). P>
La valeur de cette idée est que si vous ajoutez ou soustrayez des angles, vous obtiendrez une valeur dont la fraction vous Vous voulez, et quelle partie entière vous voulez jeter. Si nous représentons la fraction en tant que numéro de point fixe de 32 bits avec le point binaire à 2 ^ 32 (par exemple, à gauche de ce qui est normalement considéré comme un bit de signe), les débordements de la fraction tombent tout simplement sur le dessus du Valeur 32 bits gratuitement. Donc, vous faites toutes les mathématiques entier et «débordement» se passe gratuitement. P>
Donc, je réécris votre code (préservant l'idée de degrés Times 10): P>
typedef unsigned int32 angle; // angle*3600/(2^32) represents degrees #define angle_scale_factor 1193046.47111111 // = 2^32/3600 #define make_angle(degrees) (unsigned int32)((degrees%3600)*angle_scale_factor ) #define make_degrees(angle) (angle/(angle_scale_factor*10)) // produces float number ... angle a = make_angle(100); // compiler presumably does compile-time math to compute 119304647 angle b = make_angle(200); // = 238609294 angle c = a - b; // compiler should generate integer subtract, which computes 4175662649 #if 0 // no need for this at all; other solutions execute real code to do something here if (c < 0) // this can't happen { c += 3600; } // this is the wrong representation for our variant #endif // speed doesn't matter here, we're doing output: printf("final angle %f4.2 = \n", make_degrees(c)); // should print 350.00
Pourquoi es-tu inquiet pour la branche? L'alternative est quelque chose comme
((a - b) + 3600)% 3600 code>. Cela suppose
A code> et
b code> se trouvent dans la plage
0..3600 code> déjà; S'ils ne sont pas sous contrôle, la solution la plus générale est celle de McGowen suggère: ((A - B)% 3600 + 3600)% 3600`. La branche Miss doit être très coûteuse pour faire autant de calcul.
Une astuce que j'avais l'habitude d'utiliser serait
((a - b)% 3600 + 3600)% 3600 code> - cependant avec deux opérateurs de modulus, vous pourriez effectivement mieux à utiliser la comparaison
@Jonathanleffler Nous avons un vieux compilateur mauvais mais optimisé. Il génère des branches gonflées. Je viens de vérifier vos réponses, chacun produit des instructions de montage et un code plus facile à maintenir. Si vous pouviez vous fournir les deux une réponse, je peux vous donner un uppote et accepter Jonathan. Je n'ai pas besoin de 2 ops Module. Les deux valeur
A code> et
b code> sont sous notre propre contrôle.
Sent comme une optimisation prématurée pour moi. Si vous avez une CPU qui prend en charge des mouvements conditionnels ou d'autres alternatives pour générer un code sans succursale et un compilateur décemment moderne qui prend en charge la CPU, il risque de générer un code sans succursale pour vous, même si vous utilisez
si (...) { } code> ... En outre, l'opérateur MOD pourrait être plus lent qu'une branche courte du code qui est probablement déjà en cache ...
Il génère également moins de cycles.
@Twalberg Ce n'est pas le cas. Old Fujitsu Compilateur. Même le microprocesseur plus ancien. Pas de mouvements conditionnels, pas de choses à picité fantaisie. Sauf pour un diviseur matériel