web-dev-qa-db-fra.com

Entier non signé en Javascript

Je travaille sur une page qui traite les informations d'adresse IP, mais elle s'étouffe sur le fait que les entiers sont signés. J'utilise des opérateurs au niveau du bit pour l'accélérer, mais le 64e bit (indicateur signé/non signé) le gâche.

Existe-t-il un moyen de forcer un numéro à ne pas être signé en Javascript? Cela semble fonctionner correctement, jusqu'à ce que le sous-réseau soit supérieur à 30 ou inférieur à 2.

Essaye ça:

<html>
<body>

<script type='text/javascript'>
document.write( (1 << 30) +"<br/>");
document.write( (1 << 31) +"<br/>");
document.write( (1 << 32) +"<br/>");
</script>

</body>
</html>

Résultat:

1073741824 -2147483648 1

37
bradlis7
document.write( (1 << 31) +"<br/>");

L'opérateur << Est défini comme travaillant sur des entiers 32 bits signés (convertis à partir du stockage Number natif du flottant double précision). 1<<31 Doit donc donner un nombre négatif.

Le seul opérateur JavaScript qui fonctionne avec des entiers 32 bits non signés est >>>. Vous pouvez l'exploiter pour convertir un nombre entier signé sur lequel vous avez travaillé avec les autres opérateurs au niveau du bit en un nombre entier non signé:

document.write(( (1<<31)>>>0 )+'<br />');

Pendant ce temps:

document.write( (1 << 32) +"<br/>");

ne fonctionnera pas car toutes les opérations de décalage n'utilisent que les 5 bits de décalage les plus faibles (en JavaScript et dans d'autres langages de type C également). <<32 Est égal à <<0, C'est-à-dire. pas de changement.

78
bobince

Utilisez >>> au lieu de >> pour obtenir un décalage vers la droite non signé au lieu d'un prolongateur de signe. Tous les autres opérateurs au niveau du bit se comportent de la même manière, que les entiers soient signés ou non.

Votre code cassant "lorsque le sous-réseau ... est inférieur à 2" est préoccupant. Cela semble que vous puissiez avoir un bug sans rapport avec la signature des entiers.

9
moonshadow

Douglas Crockford estime que les opérateurs au niveau du bit est l'une des mauvaises parties du javascript:

En Java, les opérateurs au niveau du bit fonctionnent avec des entiers. JavaScript n'a pas d'entiers. Il n'a que des nombres à virgule flottante double précision. Ainsi, les opérateurs au niveau du bit convertissent leurs opérandes numériques en entiers, font leur travail, puis les reconvertissent. Dans la plupart des langues, ces opérateurs sont très proches du matériel et très rapides. En JavaScript, ils sont très loin du matériel et très lents. JavaScript est rarement utilisé pour la manipulation de bits.

- Douglas Crockford dans "JavaScript: The Good Parts", Annexe B, Opérateurs au niveau du bit (c'est nous qui soulignons)

Êtes-vous sûr que les opérateurs au niveau du bit accélèrent vraiment votre logique?

9
Artem Latyshev

Javascript n'a pas d'entiers, tous les nombres sont en fait doubles.

Référence Javascript 1.5 par Mozilla suggère que l'on ne peut utiliser les opérations au niveau du bit en toute sécurité que pour les nombres de 32 bits.

6
Georg Schölly

Voici deux fonctions qui convertissent les adresses ipv4 en/à partir d'entiers non signés en javascript:

function ip2long(ip) {
    var ipl=0;
    ip.split('.').forEach(function( octet ) {
        ipl<<=8;
        ipl+=parseInt(octet);
    });
    return(ipl >>>0);
}

function long2ip (ipl) {
    return ( (ipl>>>24) +'.' +
        (ipl>>16 & 255) +'.' +
        (ipl>>8 & 255) +'.' +
        (ipl & 255) );
}
3
Francis Turner

De quel type d'adresses IP disposez-vous? IPv4 n'utilise que des adresses 32 bits, donc JavaScript devrait être correct (en utilisant double qui vous donne un partie entière 52 bits ). IPv6 utilise des adresses 128 bits, vous devrez donc utiliser un tableau. Je suppose que quelque chose d'autre est cassé.

[EDIT] Construisez une petite bibliothèque qui utilise un tableau de deux entrées comme type de données interne.

0
Aaron Digulla