Java 中的按位乘法和加法
我有同时进行乘法和加法的方法,但我无法理解它们。它们都来自外部网站,而不是我自己的:
public static void bitwiseMultiply(int n1, int n2) {
int a = n1, b = n2, result=0;
while (b != 0) // Iterate the loop till b==0
{
if ((b & 01) != 0) // Logical ANDing of the value of b with 01
{
result = result + a; // Update the result with the new value of a.
}
a <<= 1; // Left shifting the value contained in 'a' by 1.
b >>= 1; // Right shifting the value contained in 'b' by 1.
}
System.out.println(result);
}
public static void bitwiseAdd(int n1, int n2) {
int x = n1, y = n2;
int xor, and, temp;
and = x & y;
xor = x ^ y;
while (and != 0) {
and <<= 1;
temp = xor ^ and;
and &= xor;
xor = temp;
}
System.out.println(xor);
}
我尝试进行逐步调试,但它对我来说确实没有多大意义,尽管它有效。
我可能正在寻找的是尝试并理解它是如何工作的(也许是数学基础?)。
编辑:这不是家庭作业,我只是想学习 Java 中的按位运算。
I have the methods that do both the multiplication and addition, but I'm just not able to get my head around them. Both of them are from external websites and not my own:
public static void bitwiseMultiply(int n1, int n2) {
int a = n1, b = n2, result=0;
while (b != 0) // Iterate the loop till b==0
{
if ((b & 01) != 0) // Logical ANDing of the value of b with 01
{
result = result + a; // Update the result with the new value of a.
}
a <<= 1; // Left shifting the value contained in 'a' by 1.
b >>= 1; // Right shifting the value contained in 'b' by 1.
}
System.out.println(result);
}
public static void bitwiseAdd(int n1, int n2) {
int x = n1, y = n2;
int xor, and, temp;
and = x & y;
xor = x ^ y;
while (and != 0) {
and <<= 1;
temp = xor ^ and;
and &= xor;
xor = temp;
}
System.out.println(xor);
}
I tried doing a step-by-step debug, but it really didn't make much sense to me, though it works.
What I'm possibly looking for is to try and understand how this works (the mathematical basis perhaps?).
Edit: This is not homework, I'm just trying to learn bitwise operations in Java.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
让我们首先看一下乘法代码。这个想法实际上非常聪明。假设您有 n1 和 n2 以二进制形式编写。那么您可以将 n1 视为 2 的幂之和: n2 = c30 230 + c29 229< /sup> + ... + c1 21 + c0 20,其中每个 c< sub>i 是 0 或 1。那么您可以将乘积 n1 n2 视为
n1 n< sub>2 =
n1 (c30 230 + c29 2 29 + ... + c1 21 + c0 20) =
n 1 c30 230 + n1 c29 229 + ... + n1 c1 21 + n1 c 0 20
这有点密集,但其思想是两个数字的乘积由第一个数字乘以组成第二个数字的 2 的幂,乘以第二个数字的二进制数字的值。
现在的问题是我们是否可以在不进行任何实际乘法的情况下计算这个和的项。为此,我们需要能够读取 n2 的二进制数字。幸运的是,我们可以通过轮班来做到这一点。特别是,假设我们从 n2 开始,然后只查看最后一位。那是c0。如果我们将值向下移动一位,则最后一位是 c0,依此类推。更一般地,在将 n2 的值向下移动 i 个位置后,最低位为 ci。要读取最后一位,我们只需将值与数字 1 进行按位与。这具有二进制表示形式,除了最后一位数字之外,所有位置都为零。由于对于任何 n 0 AND n = 0,这会清除所有最高位。此外,由于 0 AND 1 = 0 和 1 AND 1 = 1,因此此操作保留数字的最后一位。
好的 - 我们现在知道我们可以读取 ci 的值;所以呢?好消息是,我们还可以以类似的方式计算序列 n1 2i 的值。特别地,考虑值序列 n1 << 0, n1 << 1 等。任何时候进行左移,都相当于乘以 2 的幂。这意味着我们现在拥有计算上述总和所需的所有组件。这是您的原始源代码,评论了正在发生的事情:
希望这有帮助!
Let's begin by looking the multiplication code. The idea is actually pretty clever. Suppose that you have n1 and n2 written in binary. Then you can think of n1 as a sum of powers of two: n2 = c30 230 + c29 229 + ... + c1 21 + c0 20, where each ci is either 0 or 1. Then you can think of the product n1 n2 as
n1 n2 =
n1 (c30 230 + c29 229 + ... + c1 21 + c0 20) =
n1 c30 230 + n1 c29 229 + ... + n1 c1 21 + n1 c0 20
This is a bit dense, but the idea is that the product of the two numbers is given by the first number multiplied by the powers of two making up the second number, times the value of the binary digits of the second number.
The question now is whether we can compute the terms of this sum without doing any actual multiplications. In order to do so, we're going to need to be able to read the binary digits of n2. Fortunately, we can do this using shifts. In particular, suppose we start off with n2 and then just look at the last bit. That's c0. If we then shift the value down one position, then the last bit is c0, etc. More generally, after shifting the value of n2 down by i positions, the lowest bit will be ci. To read the very last bit, we can just bitwise AND the value with the number 1. This has a binary representation that's zero everywhere except the last digit. Since 0 AND n = 0 for any n, this clears all the topmost bits. Moreover, since 0 AND 1 = 0 and 1 AND 1 = 1, this operation preserves the last bit of the number.
Okay - we now know that we can read the values of ci; so what? Well, the good news is that we also can compute the values of the series n1 2i in a similar fashion. In particular, consider the sequence of values n1 << 0, n1 << 1, etc. Any time you do a left bit-shift, it's equivalent to multiplying by a power of two. This means that we now have all the components we need to compute the above sum. Here's your original source code, commented with what's going on:
Hope this helps!
看起来你的问题不是java,而只是用二进制数进行计算。简单的开始:
(所有数字均为二进制:)
好的...您看到可以使用异或运算将两个一位数字相加。使用 and 您现在可以查明是否有“进位”位,这与用笔和纸相加数字非常相似。 (到目前为止,您已经有了一个称为半加器的东西)。当您添加接下来的两位时,您还需要将进位位添加到这两位数字上。考虑到这一点,您可以获得一个全加器。您可以在维基百科上了解半加器和全加器的概念:
http://en.wikipedia.org/wiki/Adder_(电子产品)
网络上还有更多地方。
我希望这能给你一个开始。
顺便说一句,乘法与乘法非常相似。只要记住你在小学时如何用笔和纸做乘法即可。这就是这里发生的事情。只是它发生在二进制数而不是十进制数上。
It looks like your problem is not java, but just calculating with binary numbers. Start of simple:
(all numbers binary:)
Ok... You see that you can add two one digit numbers using the xor operation. With an and you can now find out whether you have a "carry" bit, which is very similar to adding numbers with pen&paper. (Up to this point you have something called a Half-Adder). When you add the next two bits, then you also need to add the carry bit to those two digits. Taking this into account you can get a Full-Adder. You can read about the concepts of Half-Adders and Full-Adders on Wikipedia:
http://en.wikipedia.org/wiki/Adder_(electronics)
And many more places on the web.
I hope that gives you a start.
With multiplication it is very similar by the way. Just remember how you did multiplying with pen&paper in elementary school. Thats what is happening here. Just that it's happening with binary numbers and not with decimal numbers.
bitwiseAdd 方法的说明:
我知道这个问题不久前就被问到了,但由于没有给出关于 bitwiseAdd 方法如何工作的完整答案,这里就是一个。
理解bitwiseAdd中封装的逻辑的关键在于加法运算与异或和与按位运算之间的关系。该关系由以下等式定义(有关该等式的数值示例,请参阅附录 1):
或者更简单地说:
您可能已经注意到该等式中有些熟悉的内容:and 和 xor< /strong> 变量与 bitwiseAdd 开头定义的变量相同。还有一个乘以 2 的操作,在 bitwiseAdd 中是在 while 循环开始时完成的。但我稍后会再谈这个。
让我也对“&”做一个简短的旁注在我们继续下一步之前,按位运算符。 该运算符基本上“捕获”应用它的位序列的交集。例如,9& 13 = 1001 & 1101 = 1001 (=9)。从这个结果中您可以看到,只有两个位序列共有的位才会被复制到结果中。由此推导出,当两个比特序列没有公共比特时,应用“&”的结果对它们产生0。 这对按位加法关系产生了重要的影响,很快就会变得清晰
现在我们遇到的问题是方程 1.2 使用了“+”运算符,而 bitwiseAdd 没有(它只使用了“^”) 、“&”和“<<”)。那么我们如何才能让等式 1.2 中的“+”消失呢?答案:通过“强制”and 表达式返回 0。我们这样做的方法是使用递归。
为了演示这一点,我将递归方程 1.2 一次(此步骤一开始可能有点困难,但如果需要,附录 2 中有详细的逐步结果):
或者更简单地说:
这里有一些有趣的事情需要注意。首先,您注意到递归的概念听起来很接近循环的概念,就像实际上在 bitwiseAdd 中发现的那样。当您考虑 and[1] 和 xor[1] 是什么时,这种联系变得更加明显:它们与 and 是相同的表达式和 xor 表达式在 bitwiseAdd 的 while 循环内部定义。我们还注意到出现了一个模式:方程 1.4 看起来与方程 1.2 完全一样!
因此,如果保留递归符号,则进一步递归是轻而易举的事。在这里,我们将方程 1.2 再递归两次:
现在应该突出显示 bitwiseAdd 中的“temp”变量的作用:temp 允许从一个递归级别传递到下一个递归级别。
我们还注意到所有这些方程中都乘以二。如前所述,此乘法是在 bitwiseAdd 中的 while 循环开始时使用 and <<= 1 语句完成的。这种乘法会对下一个递归阶段产生影响,因为 and[i] 中的位与前一阶段的 and[i] 中的位不同(如果您还记得我之前关于 '&' 所做的小旁注)运算符,您现在可能知道这是怎么回事了)。
方程 1.4 的一般形式现在变为:
最终:
那么这个递归业务到底什么时候结束呢?
答案:当等式1.5的and[x]表达式中的两个比特序列之间的交集返回0时结束。当 while 循环条件变为 false 时,bitwiseAdd 中的等效操作就会发生。此时方程 1.5 变为:
这解释了为什么在 bitwiseAdd 中我们只在最后返回xor!
我们完成了!这是一段非常聪明的代码,我必须说:)
我希望这有帮助
附录:
1)方程1.1的数字示例
方程1.1说:
要验证这个陈述一可以举一个简单的例子,比如将 9 和 13 加在一起。步骤如下所示(按位表示在括号中):
我们将
其
代入方程 1.1,我们发现:
2) 演示第一个递归步骤
演示中的第一个递归方程(方程 1.3 )表示
如果
那么
为了得到这个结果,我们只需采用上面等式 1.2 的 2* 和 + xor 部分,并应用等式给出的加法/按位操作数关系 1.1 到它。这被证明如下:
如果
那么
用方程 1.2 的 and 和 xor 变量的定义来简化它给出方程 1.3 的结果:
并且使用相同的简化给出方程1.4的结果:
EXPLANATION OF THE bitwiseAdd METHOD:
I know this question was asked a while back but since no complete answer has been given regarding how the bitwiseAdd method works here is one.
The key to understanding the logic encapsulated in bitwiseAdd is found in the relationship between addition operations and xor and and bitwise operations. That relationship is defined by the following equation (see appendix 1 for a numeric example of this equation):
Or more simply:
You might have noticed something familiar in this equation: the and and xor variables are the same as those defined at the beginning of bitwiseAdd. There is also a multiplication by two, which in bitwiseAdd is done at the beginning of the while loop. But I will come back to that later.
Let me also make a quick side note about the '&' bitwise operator before we proceed further. This operator basically "captures" the intersection of the bit sequences against which it is applied. For example, 9 & 13 = 1001 & 1101 = 1001 (=9). You can see from this result that only those bits common to both bit sequences are copied to the result. It derives from this that when two bit sequences have no common bit, the result of applying '&' on them yields 0. This has an important consequence on the addition-bitwise relationship which shall become clear soon
Now the problem we have is that equation 1.2 uses the '+' operator whereas bitwiseAdd doesn't (it only uses '^', '&' and '<<'). So how do we make the '+' in equation 1.2 somehow disappear? Answer: by 'forcing' the and expression to return 0. And the way we do that is by using recursion.
To demonstrate this I am going to recurse equation 1.2 one time (this step might be a bit challenging at first but if needed there's a detailed step by step result in appendix 2):
Or more simply:
There's a couple of interesting things to note here. First you noticed how the concept of recursion sounds close to that of a loop, like the one found in bitwiseAdd in fact. This connection becomes even more obvious when you consider what and[1] and xor[1] are: they are the same expressions as the and and xor expressions defined INSIDE the while loop in bitwiseAdd. We also note that a pattern emerges: equation 1.4 looks exactly like equation 1.2!
As a result of this, doing further recursions is a breeze, if one keeps the recursive notation. Here we recurse equation 1.2 two more times:
This should now highlight the role of the 'temp' variable found in bitwiseAdd: temp allows to pass from one recursion level to the next.
We also notice the multiplication by two in all those equations. As mentioned earlier this multiplication is done at the begin of the while loop in bitwiseAdd using the and <<= 1 statement. This multiplication has a consequence on the next recursion stage since the bits in and[i] are different from those in the and[i] of the previous stage (and if you recall the little side note I made earlier about the '&' operator you probably see where this is going now).
The general form of equation 1.4 now becomes:
FINALY:
So when does this recursion business end exactly?
Answer: it ends when the intersection between the two bit sequences in the and[x] expression of equation 1.5 returns 0. The equivalent of this in bitwiseAdd happens when the while loop condition becomes false. At this point equation 1.5 becomes:
And that explains why in bitwiseAdd we only return xor at the end!
And we are done! A pretty clever piece of code this bitwiseAdd I must say :)
I hope this helped
APPENDIX:
1) A numeric example of equation 1.1
equation 1.1 says:
To verify this statement one can take a simple example, say adding 9 and 13 together. The steps are shown below (the bitwise representations are in parenthesis):
We have
And
pluging that back into equation 1.1 we find:
2) Demonstrating the first recursion step
The first recursion equation in the presentation (equation 1.3) says that
if
then
To get to this result, we simply took the 2* and + xor part of equation 1.2 above and applied the addition/bitwise operands relationship given by equation 1.1 to it. This is demonstrated as follow:
if
then
Simplifying this with the definitions of the and and xor variables of equation 1.2 gives equation 1.3's result:
And using that same simplification gives equation 1.4's result:
这是乘法的另一种方法
Here is another approach for Multiplication