BigInteger 无符号左移或右移
我正在 int 中使用 BigInteger 重新实现一个函数。现在有步骤了
h = n >>> log2n--
,但我在这里遇到了麻烦。原始代码中h、n、log2n都是int类型,如果我将h、n、log2n设置为BigInteger,上面代码的等价表达式是什么?如何在 BigInteger 中执行无符号右移 (>>)?
编辑: 代码块是:
int log2n = 31 - Integer.numberOfLeadingZeros(n);
int h = 0, shift = 0, high = 1;
while (h != n)
{
shift += h;
h = n >>> log2n--;
int len = high;
high = (h & 1) == 1 ? h : h - 1;
len = (high - len) / 2;
if (len > 0)
{
p = p.multiply(product(len));
r = r.multiply(p);
}
}
I am reimplementing a function using BigInteger in place in int. Now there is step
h = n >>> log2n--
But I am facing trouble here. In original code h, n, log2n all are int type, if I set h, n, and log2n to BigInteger what will be the equivalent expression of the above code? How do I perform an unsigned right shift (>>>) in BigInteger?
Edit:
The code block is :
int log2n = 31 - Integer.numberOfLeadingZeros(n);
int h = 0, shift = 0, high = 1;
while (h != n)
{
shift += h;
h = n >>> log2n--;
int len = high;
high = (h & 1) == 1 ? h : h - 1;
len = (high - len) / 2;
if (len > 0)
{
p = p.multiply(product(len));
r = r.multiply(p);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
引用Java文档:
-1 的 32 位整数表示为(二进制)
如果对此使用有符号右移运算符 (
>>
),您将得到相同的结果。如果您对此使用无符号右移运算符,移位 1,您将得到
But BigInteger has an unlimited length。 BigInteger 中 -1 的表示理论上是
无符号右移运算符意味着您将 0 放在最左边的点 - 即无穷大。由于这没有什么意义,因此省略了该运算符。
至于您的实际代码,您现在需要做什么取决于周围代码正在做什么以及为什么为原始代码选择无符号移位。像这样的东西
可能有效,但这一切都取决于具体情况。
Quoting from the Java docs:
An 32-bit integer representation of -1 is (in binary)
If you use the signed right-shift operator (
>>
) on this, you'll geti.e. the same thing. If you use the unsigned right-shift operator on this, shifting by 1, you'll get
But BigInteger has an unlimited length. The representation of -1 in a BigInteger is theoretically
The unsigned right-shift operator would imply that you were putting a 0 at the leftmost point - which is at infinity. Since this makes little sense, the operator is omitted.
As regards your actual code, what you need to do now depends on what the surrounding code is doing and why an unsigned shift was chosen for the original code. Something like
might work, but it all depends on the circumstances.
我终于找到了一个解决方案,它很糟糕,但它有效:
整数为正的情况是微不足道的,因为 shiftRight 无论如何都会返回正确的结果。但对于负数,这会变得棘手。前面提到的取反版本不起作用,因为 BigInteger 中的 -1 取反是 1。将其移位,得到 0。但是您需要知道 BigInteger 的宽度是多少。然后,您基本上可以通过减去开场符来强制 BigInteger 至少具有 width+1 位。然后执行移位,并掩盖您引入的额外位。使用什么开启器并不重要,只要它不改变较低的位即可。
开启器的工作原理:
BigInteger 实现仅存储负数的最高 0 位置。 -3 表示为:
但只存储了一些位,我将其他位标记为 X。
向右移位没有任何作用,因为总是有 1 来自左侧。因此,我们的想法是减去 1 以在您感兴趣的宽度之外生成 0。假设您关心最低的 12 位:
这会强制生成真正的 1。然后向右移动,比如 5。
然后屏蔽它:
从而收到正确的结果:
因此,零的引入迫使 BigInteger 实现将存储的 0 位置更新为比您感兴趣的宽度更高的宽度并强制创建存储的 1。
I finally found a solution, it's awful, but it works:
The case that your integer is positive is trivial, as shiftRight will return the correct result anyway. But for negative numbers this gets tricky. The negate version mentioned earlier does not work as -1 in BigInteger negated is 1. Shift it and you have 0. But you need to know what the width of your BigInteger is. You then basically force the BigInteger to have at least width+1 bits by subtracting an opener. Then you perform the shifting, and mask away the extra bit that you introduced. It doesn't really matter what opener you use, as long as it doesn't alter the lower bits.
How the opener works:
The BigInteger implementation does only store the highest 0 position for negative numbers. A -3 is represented as:
But only some bits are stored, I marked the others as X.
Shifting to the right does nothing as there are always 1's coming from the left. So the idea is to substract a 1 to generate a 0 outside of the width that you are interested in. Assuming you care about the lowest twelve bit:
This forced the generation of real 1s. You then shift right by lets say 5.
And then mask it:
And therewith receive the correct result:
So the introduction of the zero forced the BigInteger implementation to update the stored 0 position to a width that is higher than the one you are interested in and forced the creation of stored 1s.
BigInteger类有以下操作
The BigInteger class has the following operations