10
votes

Opérations bitwises avec de gros entiers

Je suis en train de mettre en œuvre le décodage des entiers compressés BER et je suis récemment trouvé un comportement bizarre JavaScript relatif aux opérations bitwises avec de gros entiers.

par exemple: p>

var a = 17516032;          // has 25 bits
alert(a << 7)              // outputs -2052915200
alert(a * 128)             // outputs  2242052096
alert(2242052096 >> 16)    // outputs -31325
alert(2242052096 / 65536)  // outputs  34211


6 commentaires

Je ne comprends pas pourquoi la division ne serait-elle pas acceptable?


@Guffa J'ai besoin d'une approche générale, non seulement pour les entiers 32 bits.


La division n'est pas effectuée sur des entiers, il est effectué sur des numéros de points flottants, donc je ne comprends pas votre argument. En outre, un numéro de point flottant à double précision ne peut représenter qu'un entier 53 bits, de sorte que ce n'est pas beaucoup de toute façon si vous souhaitez décoder des nombres compressés BER.


@Guffa j'ai besoin de 16 bits d'un entiers. La division par 65536 ne fonctionnera pas bien si le nombre n'est pas divisé par 65536 (sûr, je peux faire math.floor (x / 65536) mais ça n'a pas l'air bien).


Donc, vous voulez juste quelque chose qui fait la même chose, mais semble différemment?


Que diriez-vous de ~~ (x * 152587890625e-16) ?


4 Réponses :


5
votes

Les opérateurs bitwises fonctionnent sur des entiers 32 bits, tandis que la multiplication et la division fonctionnent sur des chiffres de points flottants.

Lorsque vous déplacez un nombre, il est converti d'un numéro de point flottant en un entier 32 bits avant les opérations et reconverti sur un numéro de point flottant après l'opération. Le numéro 2242052096 a le 32ème bit défini, de sorte qu'il s'agit d'un nombre négatif lorsqu'il est converti vers et à partir d'un entier 32 bits.

Le >> Opérateur de décalage à droite ne modifie pas le signe de la valeur, c'est-à-dire. Les bits déplacés à partir de gauche ont la même valeur que le bit de signalisation. Utilisez le >>>> Opérateur de changement de droite pour passer à zéro bits à la place.

Référence: MDN: Opérateurs Bitwise


0 commentaires

2
votes

(2242052096/65536) == (2242052096 >>> 16)

Notez le quart différent.


0 commentaires

7
votes

17516032 en binaire est 000000010000001011010001100000000000 . Le déplacement vers la gauche par 7 vous donne 1000010110100011000000000000000000 . Ceci est égal à -2052915200 dans Complément de deux's's's (qui est Comment presque tous les ordinateurs représentent des nombres négatifs).

>> est un changement de droite signé. Cela signifie que le bit le plus à gauche (qui détermine le signe d'un nombre) sera décalcuté dans le côté gauche.

par exemple par exemple xxx

si vous voulez Faites un décalage non signé (qui ignore le bit de signalisation), utilisez >>> qui remplira zéro à l'extrémité gauche du bitstring.


2 commentaires

C'est ça, merci! Avez-vous une idée de la raison pour laquelle le changement de vitesse produit un résultat étrange?


Aucun problème. Édité ma réponse pour inclure cela.



1
votes

JavaScript représente normalement des chiffres en tant que point flottant (double précision).

Presque toutes les opérations bitwises se convertissent en un entier 32 bits signé, faites tout ce qu'ils vont faire, puis traiter le résultat comme une 32- BIT ENTREGER lors de la conversion de retour. P>

L'exception est >>> code> qui traite le résultat comme un entier non signé em> 32 bits lors de la conversion. p>

donc: p>

  • Les mouvements de droite peuvent être effectués pour fonctionner simplement en utilisant >>> code> au lieu de >> code>; li>
  • a * 128 code> donne la réponse attendue car elle n'est jamais convertie en un entier 32 bits signé en premier lieu - c'est juste une multiplication à virgule flottante; Li>
  • a donne une réponse inattendue car elle est convertie en un entier 32 bits signé, puis vous modifiez un 1 code> dans le bit de signalisation, ce qui entraîne un Valeur négative signée 32 bits. Li> ul>

    Il n'y a pas de , mais si vous souhaitez écrire votre décalage de gauche sous forme de décalage, vous pouvez utiliser P>

    (a << 7) >>> 0
    


1 commentaires

Joli. Merci pour l'explication!