50

我正在处理一个处理 IP 地址信息的页面,但是整数被签名的事实令人窒息。我正在使用按位运算符来加速它,但是第 64 位(有符号/无符号标志)把它搞砸了。

有没有办法强制一个数字在 Javascript 中无符号?它似乎工作正常,直到子网大于 30 或小于 2。

试试这个:

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

结果:

1073741824 -2147483648 1

4

7 回答 7

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

<<运算符被定义为处理带符号的 32 位整数(从双精度浮点数的本机数字存储转换而来)。所以1<<31必然产生负数。

使用无符号 32 位整数的唯一 JavaScript 运算符是>>>. 您可以利用它来将您一直在使用其他按位运算符处理的有符号整数转换为无符号整数:

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

同时:

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

不起作用,因为所有移位操作仅使用最低 5 位移位(在 JavaScript 和其他类似 C 的语言中也是如此)。<<32等于<<0,即。不用找了。

于 2009-12-15T16:31:22.367 回答
11

Douglas Crockford 认为位运算符是 javascript 的坏处之一:

在 Java 中,按位运算符处理整数。JavaScript 没有整数。它只有双精度浮点数。因此,按位运算符将其数字操作数转换为整数,执行其业务,然后将它们转换回来。在大多数语言中,这些运算符非常接近硬件并且速度非常快。在 JavaScript 中,它们离硬件很远,而且速度很慢。JavaScript 很少用于位操作。

-- Douglas Crockford 在“JavaScript: The Good Parts”,附录 B,按位运算符(添加了重点)

您确定按位运算符真的可以加快您的逻辑吗?

于 2009-12-15T18:14:04.937 回答
9

使用 >>> 而不是 >> 来获得无符号右移而不是符号扩展。无论整数是否带符号,所有其他按位运算符的行为方式都相同。

您的代码破坏“当子网 ... 小于 2”时令人担忧。听起来您可能有一些与整数符号无关的错误。

于 2009-12-15T16:13:41.153 回答
6

Javascript 没有整数,所有数字实际上都是双精度数。

Mozilla的Javascript 1.5 Reference建议只能对 32 位数字安全地使用按位运算。

于 2009-12-15T16:08:56.153 回答
4

这里有两个函数可以在 javascript 中将 ipv4 地址转换为无符号整数/从无符号整数转换:

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) );
}
于 2011-09-14T10:17:43.753 回答
0

你有什么样的IP地址?IPv4 仅使用 32 位地址,因此 JavaScript 应该没问题(使用 double 可以为您提供52 位整数部分)。IPv6 使用 128 位地址,因此您必须使用数组。我的猜测是其他东西坏了。

[编辑] 构建一个使用两个整数数组作为内部数据类型的小型库。

于 2009-12-15T16:11:59.880 回答
0

Javascript 现在有一个bigint类型,你可以使用n后缀来制作这样的数字。

因此,使用您的示例,您可以执行以下操作:

<body>
    
    <script type='text/javascript'>
    document.write( (1n << 30n) +"<br/>");
    document.write( (1n << 31n) +"<br/>");
    document.write( (1n << 32n) +"<br/>");
    </script>
    
    </body>
</html>
于 2021-07-22T16:04:39.550 回答