[C] décalage par un nombre négatif
Résolu
Shinjitm
Messages postés
13
Date d'inscription
Statut
Membre
Dernière intervention
-
Shinjitm Messages postés 13 Date d'inscription Statut Membre Dernière intervention -
Shinjitm Messages postés 13 Date d'inscription Statut Membre Dernière intervention -
A voir également:
- [C] décalage par un nombre négatif
- Nombre de jours entre deux dates excel - Guide
- Nombre facile - Télécharger - Outils professionnels
- Negatif telephonique - Guide
- Ascii nombre de caractères - Guide
- Mettre un 0 devant un nombre dans excel - Guide
4 réponses
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.
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
Bon sang, c'est simple, c'est si évident ... C'est parfait.
Merci !!
Merci !!
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 !
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;
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.
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) }