tre*_*der 5 javascript bit-manipulation
在其他可以代表64位整数的语言中,可以很容易地做到这一点......
// convert 64-bit n to two 32-bit x and y
x = (n & 0xFFFFFFFF00000000) >> 32
y = n & 0xFFFFFFFF
Run Code Online (Sandbox Code Playgroud)
但JavaScript不能代表64位整数.它只能代表52位整数而不会出现问题.
现在这意味着无法将64位整数转换为两个32位整数,因为它甚至不可能首先具有64位整数.
但是,我们还有52位.我的问题是:如何在JavaScript中将这个52位整数分成两个32位整数(20个高位和32个低位)
有人建议像上面的位操作代码在JavaScript中进行20位和32位拆分吗?
hex*_*wab 11
首先,您的链接包含一个小的不准确性,声明"任何小于2 52的整数将安全地放入JavaScript编号."虽然技术上正确,但它不是一个严格的限制:它可以被验证没有太多麻烦,javascript数字可以存储每个正整数高达2 53(但不是2 53 +1).
不用多说,你要求的功能,将52位数字分成底部32位和20位顶部位:
function to_int52(hi, lo) {
/* range checking */
if ((lo !== lo|0) && (lo !== (lo|0)+4294967296))
throw new Error ("lo out of range: "+lo);
if (hi !== hi|0 && hi >= 1048576)
throw new Error ("hi out of range: "+hi);
if (lo < 0)
lo += 4294967296;
return hi * 4294967296 + lo;
}
function from_int52(i) {
var lo = i | 0;
if (lo < 0)
lo += 4294967296;
var hi = i - lo;
hi /= 4294967296;
if ((hi < 0) || (hi >= 1048576)
throw new Error ("not an int52: "+i);
return { lo: lo, hi: hi };
}
Run Code Online (Sandbox Code Playgroud)
我不建议使用这些.JavaScript的按位老年退休金计划进行签名(@dandavis:JS也不会有UInt32s)和符号位引起头痛,当我们真正想要的正值.Plus V8对(有符号)整数进行了优化,可以存储为31位.结合这两个事实,你应该分割不超过30位,最大正尺寸将适合V8小整数("smi").
这是将数字拆分为30个低位和22个高位的代码:
function int52_30_get(i) {
var lo = i & 0x3fffffff;
var hi = (i - lo) / 0x40000000;
return { lo: lo, hi: hi };
}
Run Code Online (Sandbox Code Playgroud)
您可能不想创建对象.这些应该被内联(如果你真的在烦扰函数):
function int52_30_get_lo(i) {
return i & 0x3fffffff;
}
function int52_30_get_hi(i) {
return (i - (i & 0x3fffffff)) / 0x40000000;
}
Run Code Online (Sandbox Code Playgroud)
并从低和高部分创建数字:
function int52_30_new_safe(hi, lo) {
return (hi & 0x3fffff) * 0x40000000 + (lo & 0x3fffffff);
}
Run Code Online (Sandbox Code Playgroud)
如果你真的确定hi和lo在范围内,你可以跳过屏蔽:
function int52_30_new(hi, lo) {
return hi * 0x40000000 + lo;
}
Run Code Online (Sandbox Code Playgroud)
分别设置高低部件:
/* set high part of i to hi */
i = (hi & 0x3fffff) * 0x40000000 + (i & 0x3fffffff);
/* set low part of i to lo */
i += (lo & 0x3fffffff) - (i & 0x3fffffff);
Run Code Online (Sandbox Code Playgroud)
如果你确定hi和lo在范围内:
/* set high part of i to hi */
i = hi * 0x40000000 + (i & 0x3fffffff);
/* set low part of i to lo */
i += lo - (i & 0x3fffffff);
Run Code Online (Sandbox Code Playgroud)
(这些不是函数,因为它们会修改i.)
为了额外的乐趣,一个拉出任意位域的功能:
function int52_30_get_bits(i, lsb, nbits) {
while (lsb >= 32) {
i /= 4294967296;
lsb -= 32;
}
return (i / (1<<lsb)) & ((1<<nbits)-1);
}
Run Code Online (Sandbox Code Playgroud)
(nbits必须<= 31.当nbits为32时的失败模式很有意思,并且仅由于<<很重要的js操作数的5个低位,javascript规范与x86 ISA共享的缺陷).
完全可以使用符号位将53位二进制数存储为-2 53到2 53 -1的整数.我没有这样做,但它应该很容易.之后它开始变得有点毛茸茸,你最终会遇到这样一个事实,即在你达到2 64之前没有足够的浮点数(很多都是NaN).将63个二进制数字打包到一个浮点数应该在理论上是可行的,但留给读者的练习:)
另一种方法是使用类型化数组并创建一个Float视图和一个Int视图:这使您可以直接操作浮点数的基础二进制表示.但是你必须开始担心字节序等.
所有建议字符串操作的人都疯了.
| 归档时间: |
|
| 查看次数: |
2653 次 |
| 最近记录: |