8
votes

Comment simuler une rotation des bits d'un entier 64 bits (non signé) dans JavaScript?

Je dois effectuer un décalage de gauche circulaire d'un entier 64 bits en JavaScript. Cependant:

  • Les numéros JavaScript sont doubles
  • JavaScript les convertit sur INTS signé 32 bits lorsque vous commencez avec le << et le >> et le >>> et le ~ et la totalité de l'entreprise de bit-twiddling. Et puis c'est de retour aux doubles lorsque vous avez terminé. Je pense.
  • Je ne veux pas le signe. Et je ne veux certainement pas les bits décimaux. Mais je veux définitivement 64 bits.

    Ainsi, comment effectuer une rotation gauche du goutement d'une valeur de 64 bits?


6 commentaires

Savez-vous certain que votre JavaScript sera toujours exécuté sur une plate-forme 64 bits?


p.s. Des bowvotes pour quiconque me disent de ne pas le faire en JavaScript. Inutile! Et je savoir que ce n'est pas le genre de tâche que JavaScript convient bien. Mais je dois le faire quand même. Kthxbai.


Pas que je te crois, mais si JavaScript le stocke dans un double, il s'agit d'un doublé non pas d'INT de 64 bits (quel que soit le signe).


Soupir. C'est pourquoi j'ai utilisé le mot "simuler" dans la question. Je n'ai pas besoin de JavaScript pour stocker cela comme un seul INT 64 bits; J'ai juste besoin de faire quelque chose qui me donne les bonnes réponses quand je dis "Circulaire à gauche à gauche cette valeur 35 places et dites-moi quelle est la valeur INT résultante serait si nous jouions avec des INT 64 bits."


Vous voulez donc faire pivoter la représentation du bit d'un double (ou seulement 64bits) ou faites-la pivoter le nombre entier que le double représente?


Je veux faire pivoter le nombre d'entiers que le double représente. Désolé, ma question n'était peut-être pas claire; Ce que je veux, c'est faire pivoter un entier de 64 bits non signé. Je suis allé dans la représentation interne de Javascript des chiffres parce que je pensais que le manque de distinction entre les flotteurs et les INT dans JavaScript rendrait plus difficile de faire ce que je veux.


5 Réponses :


4
votes

Je le crois, bien que non le moyen le plus efficace, convertissez le nombre en une chaîne sous forme binaire (64 bits), utilisez la sous-chaîne pour déplacer le char au début et l'ajouter à la fin (pour la rotation gauche) et Convertir le formulaire binaire en nombre. Je suis sûr que vous pouvez comprendre comment convertir un nombre décimal à sa forme binaire dans une chaîne et son dos.


1 commentaires

Nah, c'est une solution légitime, même si ce n'est pas le genre de solution que j'espère. Pas de bowvotes pour vous.



0
votes

Le seul moyen, je pense que cela peut être fait est de créer une classe INT64 qui contient deux entiers 32 bits et effectue un déplacement en transportant entre eux.


0 commentaires

13
votes

Conservez votre nombre de 64 bits sous forme de partitions séparées et basses. Pour faire pivoter la gauche N quand n <32:

hi_rot = ((salut << n) | (LO >>> (32-N))) & (0xFFFFFFFFF)

lo_rot = (((LO << n) | (HI >>> (32-N))) & (0xFFFFFFFFF)

Si N> = 32, puis soustrayez 32 de N, swap hi et lo, puis faites ce qui précède.


3 commentaires

J'aime cette façon de le faire, mais le fait que les chiffres soient signés causent des gotchas? Le bit le plus important stocke le signe.


Oh, vous avez dit moins de 32 ans. On dirait que cela prend soin du problème.


Le seul problème avec c'est que & (0xffffffff) est un non-op ici. Si vous souhaitez rendre les numéros non signés, utilisez >>> 0 à la place.



0
votes

Voici une rotation basée sur des valeurs.

double d = 12345678901.0;
// get high int bits in hi, and the low in
int hi = (int)(d / 16.0 / 16.0 / 16.0 / 16.0);
int low = (int)d;

int rot = 3; // thus * 8
int newhi = (low >> (32 - rot)) | (hi << rot);
int newlow = (hi >> (32 - rot)) | (low << rot);

double newdouble = ((double)hi * 16.0 * 16.0 * 16.0 * 16.0) + (double)low;


2 commentaires

Eh bien, c'est une version C #, et à cause de la SIGNED INT La dernière étape ne fonctionne pas réellement comme prévu. Enfait, il sera probablement pas ne fonctionnera pas non plus pour des doubles négatifs éther ...


L'utilisation de l'opération arithmétique est gentiment trop lente, surtout lorsque vous souhaitez convertir une grande quantité d'octets, par exemple. données d'image, qui n'est pas une solution pratique.



1
votes

Comme @Doug Currie, vous devez représenter le nombre 64 bits sous forme de deux chiffres, puis faire des opérations bit-sage sur eux. Le code que j'ai utilisé est: xxx

Pour l'utiliser, essayez d'exécuter: console.log (nouveau long (0,1) .Rotateleft (4)); puis inspectant les propriétés _high et _low.


0 commentaires