-3
votes

moyen le plus rapide de convertir int8 en int7

J'ai une fonction qui prend int8_t val et le convertit en int7_t . xxx

Quel est le meilleur "STRT> et le plus rapide moyen de manipuler l'INT8 à int7? Est-ce que je l'ai fait efficacement et rapide? ou il y a un meilleur moyen?

La cible est ARM Cortex M0 + si cela importe

Mise à jour:

Après avoir lu différentes réponses I peut dire que la question a été réparée? (Ou mon code dans la question est ce qui a donné de mauvaises hypothèses à d'autres personnes) J'avais l'intention de faire un INT8 à INT7

afin qu'il ne soit donc fait en ne faisant rien parce que

8bit: xxx

7bit: xxx


14 commentaires

Votre masque devrait vraiment être 0b00111111 car vous ne voulez pas que le «bit de signalisation» soit défini à moins que le bit des valeurs d'origine a été défini. Notez que vous ne convertissez pas vraiment quoi que ce soit, vous ne faites que tronquer fondamentalement.


Avant "le meilleur et le plus rapide", vous devez résoudre correct . Pour cela, cependant, vous devez expliquer ce qui est censé être fait avec des valeurs d'entrée qui sont en dehors de la plage que "INT7" peut représenter.


@Johnbollinger Oh, j'ai enlevé le commentaire que je suppose que l'utilisateur appelle cette fonction qu'il sait qu'il devrait mettre des données -64 à +63. Donc, pas besoin d'aller à cette sécurité ..


wat? Donc, il suffit de masquer avec & ~ 0x80 (i.e. & 0x7f ) et être fait avec elle =?


D'accord, @hasanalattar, cela signifie-t-il que si la valeur d'entrée est hors de portée, alors vous ne vous souciez pas quelle est la sortie?


@Anttihaapala Je pense -63 serait 0B100011 en integer signé 7 bits. Et 0B1000110 en entier signé à 8 bits.


@Hasanalattar Eh bien, alors je suggère que vous alliez lire sur la représentation complémentaire de 2 de 2 en Wikipedia.


Je n'ai pas vraiment ce que votre int7_t est. Est-ce un type de complément de deux deux bits? Vous retournez un uint8_t alors que se passe-t-il avec le bit élevé? En 200 complémentations, toutes les valeurs entre -64 et 63 auront la même représentation de bits dans tous types de types de 7 ou plus. Vous slez-étendre à un type plus large en ajoutant simplement le bit de signalisation à gauche


@Anttihaapala je ne savais pas que, je voulais dire une représentation binaire ... celle que j'ai écrite.


@Pluclv Le bit le plus élevé est réservé à autre chose. Donc, cette fonction prend un numéro et la déplace vers INT7_T dans une (valeur d'octet) .. (commun à avoir d'octets dans uint8_t) ..


"Réservé" ne veut rien dire. L'important est que vous voulez effacer ce bit ou le laisser comme-est. Normalement, cela signifie souvent ne pas le toucher, auquel cas vous n'avez tout simplement rien à faire, il suffit de renvoyer toute la valeur INT8_T


@Hasanalattar Oops doit être 0B100001 et 0B11000001


@PluClv non, si une personne appelée cette fonction: func_int7_t (-63) devrait renvoyer [0BX1100001]. Ma question n'implique pas le 8ème. Je vais y traiter au bas de la fonction avant de retourner la valeur.


'donc il sera fait en ne faisant rien parce que' - Vous avez toujours accepté une réponse qui fait quelque chose qui fait quelque chose ... Il y a deux de vraiment recommander de ne rien faire du tout (accepter les Phuclv, il devait répondre d'abord ...).


5 Réponses :


6
votes

La manière plus rapide est probablement: xxx

val et 0x3f Obtenez les 6 bits inférieurs (tronqués) et (((Val >> 1) & 0x40) Déplacez le bit pour signer de la position 8 à 7

L'avantage de ne pas utiliser de si est d'avoir un code plus court (même vous pouvez utiliser arithmétique si ) et d'avoir un code sans séquence pause


13 commentaires

Cela doit être ((val >> 1) & 0x40 , sûrement?


C'est exactement ce que je voulais poster, aussi ... alternative intéressante 0xc0 , il conserverait (dupliquer le bit de signalisation dans MSB (décalage droit arithmétique fourni, mais devrait être au bras).


Ou ((VAL & 0X80) >> 1) . Et qui évite le comportement défini par la mise en œuvre associé à un numéro négatif.


@Johnbollinger i premier changement de droite alors faire le "&" pour être indépendant du fait qu'il s'agit d'un changement signé ou non, ((VAL & 0X80) >> 1) n'a pas le même résultat si le décalage signé ou non sur l'arithmétique de 8 bits (mais de l'OFC tout est fait sur int )


@Johnbollinger soit Variant est indépendant du type de décalage - Seule la mine ( & 0xc0 ) n'est pas ...


@bruno Soyez conscient de VAL étant promu à INT avant d'appliquer l'opérateur & , masquage de la signification possible du bit de la signification possible, de sorte que vous changez à droite un Int non négatif puis ...


Comment ça va, @bruno? Si vous changez d'un numéro négatif, vous obtenez un comportement défini par la mise en œuvre. En principe, cela pourrait être n'importe quoi (bien que cela soit documenté et cohérent). En pratique, bien sûr, il n'y a que deux possibilités probables, mais si vous masquez d'abord, vous évitez ce problème complètement. Même si le vôtre fonctionne très probablement, ce n'est pas strictement conforme.


@Johnbollinger La mise en œuvre définie ou non Peu importe si vous masquez toutes les autres bits que le seul pertinent - que sera déplacé sera modifié, si vous changez d'arithmétique ou logique.


Bien sûr, cela compte, @aconcagua. Bien que ce ne soit sûrement pas le cas pour le compilateur et l'environnement de la cible, une définition de la mise en œuvre du comportement d'un bon changement d'un nombre négatif pourrait être quelque chose que vous ne vous attendez pas, comme la production toujours -1.


@Johnbollinger 0b11xx (résultat de l'ASR) et 0b01xx (résultat de la LSR) donnera les mêmes résultat après avoir appliqué `& 0x0100` - le bit différent (bit 3 dans l'exemple ) Est masqué quand même ...


@Johnbollinger faisant que je laisse le compilateur à pouvoir utiliser une instruction faisant le changement sur 8 bits, quelle que soit sa signature ou non, c'est-à-dire inutile de rechercher plus :-)


C'est la méthode la plus lente de tous! Alors pourquoi a-t-il obtenu tous les upvotes?


@Tonyk La question initiale était de réécrire le code donné d'une autre manière avec le même comportement, alors je l'ai fait, et après la question a été modifiée



2
votes

Si vous n'êtes pas préoccupé par ce qui arrive à des valeurs hors de portée,

return val & 0x7f;


16 commentaires

Ainsi, -127 (0B10000001) deviendra 1. faux.


Si la valeur initiale est 0x82 (négative) 0x82 et 0x7f est 0x2 de sorte qu'une valeur positive, ce n'est pas correct


@bruno: secondé. Votre réponse semble être la manière la plus succincte.


@Andrejscainikovs, -127 n'est pas une valeur d'argumentation prise en charge. Les arguments doivent être compris entre -64 et 63, conformément à la spécification de fonction.


@bruno, 0x82 n'est pas non plus une valeur d'argumentation prise en charge.


@Johnbollinger val est int8_t de sorte qu'il peut valoriser 0x82, que voulez-vous dire?


@Johnbollinger manquée déclaration OP L'utilisateur qui appelle cette fonction l'utilisera correctement (-64 à +63) . Dans ce cas, oui, c'est la manière la plus élégante.


Si nous continuons le nombre de remarques et de réponses ne pourrons pas être comptés sur Int7 bits ^^


@bruno, les spécifications de la fonction nécessitent que l'appelant passe une valeur dans la plage 64 ... +63. Cela n'a pas été clair dans la question, mais il a été mis à jour. Le comportement lorsque l'argument est en dehors de cette plage n'est pas spécifié et ne peut donc être faux, peu importe ce que c'est.


@Johnbollinger Appelez la fonction avec (-63) devrait renvoyer [0bx1100001] qui est -63 dans la plage de 7 bits signée variable. Votre solOUTITION masque le bit des signes et nous le perdons.


@Hasanalattar: -63 est 1111111 , pas 1100001 .


^^. De plus, @hasanalattar, le bit de signalisation d'un numéro de complément de deux à 7 bits est le bit 6 (zéro), pas bit 7. L'ensemble de l'exercice consiste à renvoyer un résultat avec le bit 7 clair, n'est-ce pas?


@Johnbollinger, non et en fait j'ai commencé à sentir que cela va être compliqué. Fonction d'appel avec valeur (-63) qui est [0B11000001] doit renvoyer [0bx1111111] - à nouveau x signifie que je ne me soucie pas.


@Tonyk 1111111 est 63, -63 est 1000001. \ @hasan Alattar Personne ne se soucie de votre code. Les gens lisent la description qui n'est pas claire. Il n'y a pas de cartographie définie dans la question


@Pluclv: Vous avez raison que j'avais tort. Mais tu as eu tort aussi! 1111111 est -1 dans le complément de 7 bits 2, pas 63.


@Tonyk Ouais je pensais à la valeur INT8_T. En effet c'est faux en 7 bits



3
votes

Utilisez Bitfield pour limiter la valeur et laisser le compilateur à choisir la séquence de décalages et / ou de masques le plus efficace pour cela sur votre plate-forme.

inline uint8_t to7bit(int8_t x) 
{ 
    struct {uint8_t x:7;} s; 
    return s.x = x; 
} 


4 commentaires

Intéressant ... du point de vue de la norme, le compilateur peut choisir, s'il souhaite remplir le champ de bit de gauche à droite ou de droite à gauche (seul l'ordre des membres doit rester identique), donc au moins En théorie, ce n'est pas totalement portable. Toolchain spécifié, cependant, commence à remplir MSB, donc nous allons bien ... (En fait, je ne connais pas d'autre que ce soit qui ne le fait pas - peut-être sur une plate-forme?)


J'utilise uniquement S.x en code, tous les compilateurs que j'ai essayés (GCC, Clang, MSVC) optimisent l'utilisation totalement de celle-ci.


@Aconcagua, peu importe la façon dont le compilateur représente la valeur de Bitfield. Aucune opération utilisée dans cette approche ne dépend de celle-ci pour produire le résultat recherché. Je ne suis pas d'accord pour dire que c'est meilleur , mais cela fonctionnera bien.


@Johnbollinger La sortie est correcte dans tous les cas - un compilateur choisi pour remplir le champ Bitfield à partir de MSB peut avoir besoin (jusqu'à) deux décalages supplémentaires, cependant, et la solution pourrait ne pas être la plus rapide. .. éventuellement d'intérêt théorique que, comme mentionné déjà, je ne connais aucun compilateur de ce type ...



4
votes

Pour effacer le bit réservé, juste xxx pré>

pour laisser le bit réservé exactement comme comment il s'agissait d'une entrée, rien ne doit être fait P>

return val;


6 commentaires

Vous voulez dire [- 64,63] . Ou [- 64,64) .


@Tonyk oui, corrige la faute de frappe


Et le nettoyage du bit réservé a exactement la sémantique appropriée pour les intrants de la gamme autorisée. Nous pouvons voir que en regardant la transformation inverse: si nous avons une représentation de 7 bits de complément d'un nombre négatif, alors signer l'extension à 8 bits signifie ajouter un bit de premier plan. C'est la préservation de la valeur. Ainsi, en remontant l'autre moyen nécessite d'ignorer ou d'éliminer le bit supplémentaire.


func_int7_t (-63) devrait renvoyer [0bx1100001]. Ma question n'implique pas le 8ème. [X] = ne comporte pas si son 0 ou 1! et ce commentaire de moi a tort car il devrait retourner [0bx1111110] qui est (-63) dans (représentation binaire à 7 bits)


Cela n'a pas d'importance alors pourquoi déranger cela? Il suffit de retourner la valeur comme ci-dessus. Et -63 est pas 1111110. Avez-vous vu que le dernier bit est zéro qui indique un nombre pair? Essayez la calculatrice d'ouverture et vous verrez -63 = 1000001 immédiatement


vous avez raison. Bien que j'ai mis la première réponse, j'ai vu comme réponse correcte. Merci.



1
votes

L'utilisateur qui appelle cette fonction il sait qu'il devrait mettre des données64 à +63 p>

N'en tenant donc pas d'autres valeurs, la chose vraiment em> la plus rapide que vous puissiez faire est ne rien faire du tout strong>! p>

Vous avez un 7 bit Valeur stockée dans huit bits. Toute valeur dans une plage spécifiée aura à la fois un bit 7 et un bit 6 la même valeur, et lorsque vous traitez la valeur 7 bits, vous venez de ignorer em> la MSB (de valeur 8 bits), peu importe si Définir ou non, e. G.:

for(unsigned int bit = 0x40; bit; bit >>= 1)
//                NOT: 0x80!
    std::cout << (value & bit);


5 commentaires

Je conviens que les 7 bits à faible commande d'une entrée valide sont déjà corrects et que, par conséquent, rien ne doit être fait pour eux. C'est en fait le point des deux réponses qui suggèrent simplement de masquer l'autre. Peut-être que rien ne fait rien n'est vraiment meilleur, mais cela n'est pas cohérent avec le code exemple, qui force l'autre morceau clair.


@Johnbollinger Question est maintenant: Efface vraiment le peu une exigence ou était-ce un malentendu lorsque la question a été posée ...


Mon soloution dans la question est faux qui conduisent à de mauvaises réponses. Non et en fait j'ai commencé à sentir que cela va être compliqué. Fonction d'appel avec valeur (-63) qui est [0B11000001] doit renvoyer [0bx1111111] - x signifie que je ne me soucie pas.


@Hasanalattar Pourquoi devrait-il être 1111111? Si vous utilisez un encodage étrange au lieu du complément de deux deux, vous devez inclure la cartographie de la question [


@Hasanalattar, en complément de deux bits, 0b1111111 représente -1, pas -63. -63 serait représenté comme 0B1000001. Si vous voulez convertir une représentation de signe / magnitude, c'est une bouilloire entièrement différente de poisson.