[C] décalage par un nombre négatif
Résolu/Fermé
Shinjitm
Messages postés
13
Date d'inscription
vendredi 13 février 2009
Statut
Membre
Dernière intervention
9 novembre 2011
-
13 juin 2011 à 19:21
Shinjitm Messages postés 13 Date d'inscription vendredi 13 février 2009 Statut Membre Dernière intervention 9 novembre 2011 - 14 juin 2011 à 13:51
Shinjitm Messages postés 13 Date d'inscription vendredi 13 février 2009 Statut Membre Dernière intervention 9 novembre 2011 - 14 juin 2011 à 13:51
A voir également:
- [C] décalage par un nombre négatif
- Nombre facile - Télécharger - Outils professionnels
- Negatif +62 - Guide
- Kahoot gratuit nombre de participants - Forum Réseaux sociaux
- Dans ce fichier, réalisez le graphique xy (nuage de points ou dispersion), avec les x en abscisse. dans le graphique, les points dessinent un nombre. lequel ? - Forum Bureautique
- Decalage sous titres prime - Forum TV & Vidéo
4 réponses
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
13 juin 2011 à 20:09
13 juin 2011 à 20:09
Pourquoi ne pas faire tout simplement ceci ?
a = (c<d) ? b << (d-c) : b >> (c-d);
Shinjitm
Messages postés
13
Date d'inscription
vendredi 13 février 2009
Statut
Membre
Dernière intervention
9 novembre 2011
13 juin 2011 à 20:37
13 juin 2011 à 20:37
J'aimerais, autant que possible, éviter d'utiliser des conditions. Tous les branchements conditionnels sont consommateurs de temps de calcul ("vidage" du pipeline du processeur), ce qui est assez coûteux quand on fait du temps-réel. Un décalage est une opération de processeur, un if peut en coûter une dizaine.
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
13 juin 2011 à 20:43
13 juin 2011 à 20:43
Moins coûteux tu vas avoir ce code, mais il va réduire l'amplitude des valeurs utilisables.
En effet si tu utilises par exemple c=d très grands, tu vas déborder et perdre de la précision. Après ça peut dépendre des conditions que tu as sur c et d...
En effet si tu utilises par exemple c=d très grands, tu vas déborder et perdre de la précision. Après ça peut dépendre des conditions que tu as sur c et d...
a = (b << d) >> c
Shinjitm
Messages postés
13
Date d'inscription
vendredi 13 février 2009
Statut
Membre
Dernière intervention
9 novembre 2011
13 juin 2011 à 20:49
13 juin 2011 à 20:49
Bon sang, c'est simple, c'est si évident ... C'est parfait.
Merci !!
Merci !!
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
13 juin 2011 à 20:51
13 juin 2011 à 20:51
Mais n'oublie pas de prendre en compte ma remarque, sinon tu vas avoir des problèmes !
Shinjitm
Messages postés
13
Date d'inscription
vendredi 13 février 2009
Statut
Membre
Dernière intervention
9 novembre 2011
14 juin 2011 à 10:28
14 juin 2011 à 10:28
Je le ferai
L'opération à réaliser est la suivante :
int a;
int b;
int c;
unsigned int A;
unsigned int B;
unsigned int C;
c = (int)(((long) a * (long) b) >> (A + B - C);
Dans de nombreux cas, ça doit passer sans soucis. En se creusant un peu la cervelle, ça marchera, je ne m'en fais pas trop.
Encore merci !
L'opération à réaliser est la suivante :
int a;
int b;
int c;
unsigned int A;
unsigned int B;
unsigned int C;
c = (int)(((long) a * (long) b) >> (A + B - C);
Dans de nombreux cas, ça doit passer sans soucis. En se creusant un peu la cervelle, ça marchera, je ne m'en fais pas trop.
Encore merci !
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
14 juin 2011 à 10:51
14 juin 2011 à 10:51
Tu parlais d'efficacité en rechignant sur ma condition trop coûteuse, mais faire 3 casts comme tu le fais me paraît bien plus coûteux !
Puisque tu diminues les puissances (avec >>) je ne penses pas que tu ais besoin de faire un cast sur un type plus grand, et du coup ta multiplication sera moins coûteuse si tu diminues tes puissances avant...
En plus il me parait évident que A, B et C ne devrons pas dépasser sizeof(int) sinon il y aura dépassement de capacité, alors les mettre en unsigned int me paraît erroné...
Puisque tu diminues les puissances (avec >>) je ne penses pas que tu ais besoin de faire un cast sur un type plus grand, et du coup ta multiplication sera moins coûteuse si tu diminues tes puissances avant...
En plus il me parait évident que A, B et C ne devrons pas dépasser sizeof(int) sinon il y aura dépassement de capacité, alors les mettre en unsigned int me paraît erroné...
int a, b, c; unsigned char A,B,C; c = ( (a >> A) * (b >> B) ) << C;
Shinjitm
Messages postés
13
Date d'inscription
vendredi 13 février 2009
Statut
Membre
Dernière intervention
9 novembre 2011
14 juin 2011 à 11:19
14 juin 2011 à 11:19
J'avoue que je ne connais pas le coût, en terme de temps de calcul, d'un cast. Si tu as une information la dessus, je suis preneur.
Cela dit, je travaille actuellement sur des processeurs 32bits. Actuellement, j'utilise une librairie mathématique fournie par le fabriquant qui réalise exactement l'opération que je souhaite, mais sur des entiers 32 bits castés en 64 bits pour l'opération. Je cherche donc un moyen de réaliser l'opération en 16 / 32 bits plutôt que 32 / 64, soit pour gagner du temps de calcul, soit pour pouvoir passer sur une famille de microprocesseurs moins puissants.
Le calcul en question est de la "virgule fixe". C'est à dire que si je décrète arbitrairement que j'ai "4 bits après la virgule", le chiffre 1 est représenté par 8. Ce qui me permet d'avoir des "entiers" qui "valent" 0,125.
Avec la librairie actuelle, toutes les variable ont le même nombre de "bits après la virgule", ce qui simplifie beaucoup les calculs. Mais en passant en 16 bits, travailler de cette façon réduit considérablement l'excursion de valeurs possibles. D'où l'idée de travailler sur des paires {a,A}, a étant ma vraie variable et A le "nombre de bits après la virgule". Chaque nombre a ainsi une plage d'excursion et une précision adaptées à son utilisation.
Ta nouvelle solution, dans ce cadre, pose le problème de la précision. La précision finale souhaitée pour c est C. Si je fais le décalage de a et b avant la multiplication, je perd immédiatement tous les "chiffres après la virgule", donc beaucoup de précision, dans l'opération. Il faut donc commencer par faire la multiplication, puis le décalage dans lequel je ne garde que la précision qui m'intéresse.
Cela dit, je note ta remarque en ce qui concerne le type de A, B, C.
Cela dit, je travaille actuellement sur des processeurs 32bits. Actuellement, j'utilise une librairie mathématique fournie par le fabriquant qui réalise exactement l'opération que je souhaite, mais sur des entiers 32 bits castés en 64 bits pour l'opération. Je cherche donc un moyen de réaliser l'opération en 16 / 32 bits plutôt que 32 / 64, soit pour gagner du temps de calcul, soit pour pouvoir passer sur une famille de microprocesseurs moins puissants.
Le calcul en question est de la "virgule fixe". C'est à dire que si je décrète arbitrairement que j'ai "4 bits après la virgule", le chiffre 1 est représenté par 8. Ce qui me permet d'avoir des "entiers" qui "valent" 0,125.
Avec la librairie actuelle, toutes les variable ont le même nombre de "bits après la virgule", ce qui simplifie beaucoup les calculs. Mais en passant en 16 bits, travailler de cette façon réduit considérablement l'excursion de valeurs possibles. D'où l'idée de travailler sur des paires {a,A}, a étant ma vraie variable et A le "nombre de bits après la virgule". Chaque nombre a ainsi une plage d'excursion et une précision adaptées à son utilisation.
Ta nouvelle solution, dans ce cadre, pose le problème de la précision. La précision finale souhaitée pour c est C. Si je fais le décalage de a et b avant la multiplication, je perd immédiatement tous les "chiffres après la virgule", donc beaucoup de précision, dans l'opération. Il faut donc commencer par faire la multiplication, puis le décalage dans lequel je ne garde que la précision qui m'intéresse.
Cela dit, je note ta remarque en ce qui concerne le type de A, B, C.
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
14 juin 2011 à 11:53
14 juin 2011 à 11:53
Sur 16 bits : signed short int représente 1 valeur
1 bit de signe, 11 bits avant la virgule et 4 bits après la virgule.
Sur 32 bits : signed long int représente le produit de 2 valeurs
1 bit de signe, 1 bit inutile, 22 bits avant la virgule et 8 bits après la virgule.
Pour faire la multiplication de deux valeurs sur 16 bits, tu devras prendre un résultat sur 32 bits, et faire la multiplication. Là tu fais >>4 pour supprimer les 4 bits de précisions en trop et tu castes en 16 bits.
1 bit de signe, 11 bits avant la virgule et 4 bits après la virgule.
Sur 32 bits : signed long int représente le produit de 2 valeurs
1 bit de signe, 1 bit inutile, 22 bits avant la virgule et 8 bits après la virgule.
Pour faire la multiplication de deux valeurs sur 16 bits, tu devras prendre un résultat sur 32 bits, et faire la multiplication. Là tu fais >>4 pour supprimer les 4 bits de précisions en trop et tu castes en 16 bits.
inline signed short int multiplier( const signed short int a // 16 bits (précision 4 bits) const signed short int b) // 16 bits (précision 4 bits) { signed long int c = a; // 32 bits (précision 4 bits) c *= b // 32 bits (précision 8 bits) c >>= 4; // 32 bits (précision 4 bits) return c; // 16 bits (précision 4 bits) }