2008-12-14 8 views
9

Ceci est un suivi de my question yesterday:soustraction Bitwise en Python

CMS a aimablement fourni cet exemple d'utilisation opérateurs de bits pour additionner deux nombres en C:

#include<stdio.h> 

int add(int x, int y) { 
    int a, b; 
    do { 
     a = x & y; 
     b = x^y; 
     x = a << 1; 
     y = b; 
    } while (a); 
    return b; 
} 

int main(void){ 
    printf("6 + 3 = %d", add(6,3)); 
    printf("6 - 3 = %d", add(6,-3)); 
    return 0; 
} 

Il fonctionne très bien et je puis porté Python à Python comme suit:

def add(x, y): 
    while True: 
     a = x & y 
     b = x^y 
     x = a << 1 
     y = b 
     if a == 0: 
      break 
    return b 

print "6 + 3 = %d" % add(6,3) 
print "6 - 3 = %d" % add(6,-3) 

Ils travaillent tous les deux pour l'addition et le programme C fonctionne également pour la soustraction. Cependant, le programme Python entre dans une boucle infinie pour la soustraction. J'essaye d'aller au fond de ceci et ai posté le programme ici pour plus d'expérimentation: http://codepad.org/pb8IuLnY

Quelqu'un peut-il conseiller pourquoi il y aurait une différence entre la façon dont C gère ceci et la façon dont CPython gère ceci?

Répondre

2

Déplacement des nombres négatifs n'ont pas une interprétation cohérente entre python et C.

9

Comme je l'ai souligné dans ma réponse à la CMS « hier réponse, à gauche le déplacement d'un nombre négatif est un comportement non défini dans C si ce n » t garanti même de travailler en C (le problème est de savoir comment gérer le bit signé, le déplacez-vous comme un bit de valeur ou n'est-il pas affecté par un décalage? Le comité de normalisation n'a pas pu se mettre d'accord sur un comportement). Lorsque cela se produit en C, il repose sur des entiers de largeur de bits fixes, de sorte que le bit le plus à gauche est repoussé lorsque vous effectuez un décalage (il nécessite également que le bit de signe soit traité comme un bit de valeur pour le décalage fins). Tous les types entiers dans C sont des bits fixes mais les nombres Python peuvent être arbitrairement grands. À gauche le déplacement d'un nombre en Python fait juste continuer à obtenir plus:

>>> 1 << 100 
1267650600228229401496703205376L 

Vous pouvez essayer quelque chose comme ceci:

x = (a << 1) & 0xffffffff 

Pour limiter le résultat à 32 bits, le problème est que la L'opérateur de décalage de gauche en Python ne décale pas le bit de signe d'un nombre signé (qui fait partie de ce qui est requis pour que cette solution particulière fonctionne). Il pourrait y avoir un moyen de changer le comportement de l'opérateur de poste, mais je ne sais pas comment.

+0

Merci pour l'info. Cela signifie-t-il que la soustraction de bits n'est pas possible? Tout ce que j'ai lu en ligne suggère de le transformer en un problème d'addition binaire en prenant le complément à deux du deuxième opérande. – user23126

+0

Je pense que vous devriez changer le comportement de l'opérateur de gauche, voir ma réponse éditée. –

+0

Le décalage vers la gauche est défini en termes de multiplication en Python (http://docs.python.org/reference/expressions.html#shifting-operations) donc je pense que vous devrez trouver une autre approche si vous voulez que cela fonctionne avec des nombres négatifs . –

1

si i, j sont deux entiers:

addition:

printf("%d",(i^j)|((i&j)<<1)); 
+0

Ne pense pas que cela fonctionne. –

0

J'ai remarqué que vous êtes en supposant que les travaux de python avec des chiffres de la même façon que le fait C.
Ce n'est pas entièrement vrai. Signification Les nombres entiers de C ont une longueur fixe de 16 bits. Pour des informations détaillées sur les types de données C, vous pouvez vous référer à C_data_types on en.wikipedia.org
Pyhton, d'autre part, est dit avoir une longueur pratiquement infinie pour les nombres int.
L'ajout d'entiers positifs peut fonctionner de la même manière. Mais soustraire ou ajouter des entiers négatifs ne devrait pas être une simple traduction de mappage.
Une manière facile de comprendre un petit exemple sur des nombres négatifs: Imagine une représentation entière de longueur fixe de 3 bits:

Unsigned

  • 000: 0
  • 001: 1
  • 010: 2
  • 011: 3
  • 100: 4
  • 101: 5
  • 110: 6
  • 111: 7

Signé:

  • 000: 0
  • 001: 1
  • 010: 2
  • 011: 3
  • 100: -4
  • 101: -3
  • 110: -2
  • 111: -1

Cela fonctionne cool parce que vous peut voir que 1-3=1+(-3), -3 est 101 c'est 5 si non signé. Ainsi, 1+5=6, 6: 110: -2. Cela signifie que 1-3=-2.
il devient également buggé en débordement: - -4 + -1 = 3 pas -5 car il est hors de portée! - 3 + 1 = -4 pas 4 parce que c'est hors de portée!

Comme vous pouvez le voir, cela fonctionne pour une longueur fixe mais cela ne fonctionne pas de cette façon en Python.