Comment puis-je multiplier et diviser en utilisant uniquement le décalage de bits et l'ajout d'?
Comment puis-je multiplier et diviser en utilisant uniquement le décalage de bits et l'ajout d'?
- Comme vous le feriez sur du papier à l'école intermédiaire, en utilisant uniquement les binaires au lieu de la virgule.
- Ce manque de cette réponse? Vous êtes à la recherche pour le C ou de l'assemblée de mise en œuvre, notamment opérande largeurs, une division de la méthode (par exemple, la restauration de vs non-restauration)?
- Pour soustraction OK? Tout semble être couverts
- Quel est le besoin derrière cette question? CPU traduire de se multiplier et de la division des opérations dans bitshifting et l'ajout ou la soustraction déjà, et si c'est si le compilateur n'a pas déjà été fait.
- Juste de la curiosité, c'est plus une manière d'imaginer comment un compilateur peut travailler avec un jeu d'instructions.
imagine how a compiler can work with a restricted instruction set
la question serait mieux de laisser cela sur. Ensuite, il n'y a qu'un seul opérande connu au moment de la compilation, ou même les deux.
Vous devez vous connecter pour publier un commentaire.
À se multiplier en termes d'ajouter et de déplacement que vous souhaitez décomposer les nombres par des puissances de deux, comme suit:
(
_2
moyens de base 2)Comme vous pouvez le voir, la multiplication peut être décomposé en ajoutant des et de déplacement et de retour à nouveau. C'est aussi pourquoi la multiplication prend plus de temps que peu de postes ou l'ajout d' - il est O(n^2) plutôt que de O(n) le nombre de bits. Réel des systèmes informatiques (par opposition à la théorie des systèmes informatiques) ont un nombre fini de bits, de sorte que la multiplication prend une constante multiples de temps par rapport à l'addition et de déplacement. Si je me souviens bien, les processeurs modernes, si canalisée correctement, peut faire une multiplication à peu près aussi rapide que l'addition, par interférence avec l'utilisation de l'Utm (arithmétique unités) dans le processeur.
La réponse d'Andrew Toulouse peut être étendu à la division.
La division par des constantes entières est examiné en détail dans le livre "Hacker s Delight" par Henry S. Warren (ISBN 9780201914658).
La première idée de la mise en œuvre de la division est d'écrire l'inverse de la valeur du dénominateur dans la base de deux.
E. g.,
1/3 = (base-2) 0.0101 0101 0101 0101 0101 0101 0101 0101 .....
Donc,
a/3 = (a >> 2) + (a >> 4) + (a >> 6) + ... + (a >> 30)
pour les 32 bits de l'arithmétique.
En combinant les termes d'une façon évidente, nous pouvons réduire le nombre d'opérations:
b = (a >> 2) + (a >> 4)
b += (b >> 4)
b += (b >> 8)
b += (b >> 16)
Il y a de plus excitant façons de calculer la division et les restes.
EDIT1:
Si l'OP moyens de multiplication et de division d'un nombre arbitraire, pas la division par un nombre constant, alors ce fil pourrait être d'utilisation: https://stackoverflow.com/a/12699549/1182653
EDIT2:
L'un des moyens les plus rapides pour diviser par des constantes entières est d'exploiter l'arithmétique modulaire et Montgomery réduction: Quel est le moyen le plus rapide pour diviser un nombre entier par 3?
b += r * 11 >> 5
avecr = a - q * 3
. Lien: hackersdelight.org/divcMore.pdf page 2+.X * 2 = 1 bit shift gauche
X /2 = 1 bit décalage à droite
X * 3 = shift gauche 1 peu, puis ajouter X
add X
pour cette dernière?x << k == x multiplied by 2 to the power of k
x >> k == x divided by 2 to the power of k
Vous pouvez utiliser ces changements à faire toute opération de multiplication. Par exemple:
x * 14 == x * 16 - x * 2 == (x << 4) - (x << 1)
x * 12 == x * 8 + x * 4 == (x << 3) + (x << 2)
De diviser un nombre par une puissance de deux, je ne suis pas au courant de toute manière facile, sauf si vous voulez mettre en œuvre certaines de bas niveau de la logique, de l'utilisation d'autres opérations binaires et l'utilisation d'une certaine forme d'itération.
J'ai traduit le code Python à C. L'exemple donné avait un défaut mineur. Si la valeur du dividende qui a pris toutes les 32 bits, le changement serait un échec. J'ai juste utilisé 64 bits des variables à l'interne pour contourner le problème:
Prendre deux nombres, disons, 9 et 10, de les écrire en binaire - 1001 et 1010.
Commencer avec un résultat, R, 0.
Prendre l'un des numéros, 1010 dans ce cas, nous allons l'appeler Un, et de le déplacer à droite par un peu, si vous déplacez une, ajoutez le premier numéro, nous allons l'appeler B, R.
Maintenant shift B gauche d'un bit et répétez jusqu'à ce que tous les bits ont été décalées de A.
Il est plus facile de voir ce qui se passe si vous voyez qu'il écrit, c'est l'exemple:
Une procédure de division de nombres entiers qui utilise les quarts de et ajoute peut être dérivé en simple mode de décimales en main de la division tel qu'il est enseigné à l'école primaire. La sélection de chaque quotient chiffre est simplifié, car le chiffre est de 0 et de 1: si le solde est supérieur ou égal au diviseur, le bit le moins significatif de l'partielle quotient est 1.
Tout comme avec décimale la main de la division, les chiffres du dividende sont considérés à partir de la plus importante à la moins importante, un chiffre à la fois. Ceci est facilement accompli par un virage à gauche dans la division binaire. Aussi, le quotient bits sont recueillies par la gauche déplacer le courant du quotient de bits d'une position, puis l'ajout de la nouvelle quotient peu.
Dans un ordonnancement classique, ces deux quarts de travail sont combinés dans la gauche le déplacement d'une seule paire. La moitié supérieure détient le courant reste, la moitié inférieure initiale détient le dividende. Comme le dividende bits sont transférés vers le reste s'inscrire en virage à gauche, la partie inutilisée des bits de poids faible de la moitié inférieure sont utilisés pour accumuler le quotient de bits.
Ci-dessous est x86 langage assembleur et C implémentations de cet algorithme. Cette variante particulière d'un shift & ajouter de la division est parfois appelé la "non-exécution", une variante de la soustraction de la division de l'actuelle reste n'est pas effectué, sauf si le solde est supérieur ou égal au diviseur. En C, il n'y a pas de notion de le porter un drapeau utilisé par la version de l'assembly dans le registre de la paire de décalage vers la gauche. Au lieu de cela, il est émulé, basée sur l'observation que le résultat d'une addition modulo 2n peut être plus petit que soit addend que si il y avait une réaliser.
Prises de ici.
Ce n'est que pour la division:
Cela devrait fonctionner pour la multiplication:
La méthode ci-dessous est la mise en œuvre de binaire diviser en considérant les deux nombres sont positifs. Si la soustraction est une préoccupation que nous pouvons mettre en œuvre cette aussi bien à l'aide des opérateurs binaires.
Code
Pour la multiplication:
Pour quiconque s'intéresse à un 16-bit x86 solution, il y a un morceau de code par JasonKnight iciUn (il comprend également signé multiplier pièce, que je n'ai pas testé). Toutefois, ce code a des problèmes avec les grandes entrées, où le "add bx,bx" une partie de débordement.
La version fixe:
Ou même dans GCC assembly en ligne:
De l'essayer. https://gist.github.com/swguru/5219592