当前位置: 首页 > 面试题库 >

Java的按位乘法和加法

施飞驰
2023-03-14
问题内容

我有做乘法和加法的方法,但是我只是无法理解它们。它们都是来自外部网站,而不是我自己的:

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中的按位运算。


问题答案:

让我们开始看乘法代码。这个想法实际上很聪明。假设您有以二进制形式编写的n 1和n 2。然后,您可以将n1视为两个幂的和:n2 = c 30 2 30 +
c 29 2 29 + … + c 1 2 1 + c 0 2 0,其中每个c i为0或1。那么您可以将乘积n 1 n 2视为

n 1 n 2 =

n 1(c 30 2 30 + c 29 2 29 + … + c 1 2 1 + c 0 2 0)=

n 1 c 30 2 30 + n 1 c 29 2 29 + … + n 1 c 1 2 1 + n 1 c 0 2 0

这有点密集,但是我们的想法是,两个数字的乘积由第一个数字乘以组成第二个数字的两个数字的乘方乘以第二个数字的二进制数字的值得出。

现在的问题是,我们是否可以在不进行任何实际乘法的情况下计算该和项。为了做到这一点,我们将需要能够读取n
2的二进制数字。幸运的是,我们可以使用班次进行操作。特别地,假设我们从n 2开始,然后只看最后一位。那是c 0。如果然后将值下移一个位置,则最后一位是c
0,依此类推。更一般而言,将n 2的值下移i个位置后,最低位将是c
i。要读取最后一位,我们可以对值与数字1进行按位与运算。它具有二进制表示形式,除最后一位数字外,其他所有位置均为零。由于任何n的0 AND n =
0,因此将清除所有最高位。此外,由于0 AND 1 = 0和1 AND 1 = 1,因此此操作将保留数字的最后一位。

好的-我们现在知道我们可以读取c i的值了;所以呢?好吧,好消息是我们还可以类似的方式计算级数n 1 2 i的值。特别是,请考虑值序列n 1 << 0,n
1 << 1,依此类推。每当您进行左移时,就等于乘以2的幂。这意味着我们现在拥有计算上述总和所需的所有组件。这是您的原始源代码,并对其进行了评论:

public static void bitwiseMultiply(int n1, int n2) {
    /* This value will hold n1 * 2^i for varying values of i.  It will
     * start off holding n1 * 2^0 = n1, and after each iteration will 
     * be updated to hold the next term in the sequence.
     */
    int a = n1;

    /* This value will be used to read the individual bits out of n2.
     * We'll use the shifting trick to read the bits and will maintain
     * the invariant that after i iterations, b is equal to n2 >> i.
     */
    int b = n2;

    /* This value will hold the sum of the terms so far. */
    int result = 0;

    /* Continuously loop over more and more bits of n2 until we've
     * consumed the last of them.  Since after i iterations of the
     * loop b = n2 >> i, this only reaches zero once we've used up
     * all the bits of the original value of n2.
     */
    while (b != 0)
    {
        /* Using the bitwise AND trick, determine whether the ith 
         * bit of b is a zero or one.  If it's a zero, then the
         * current term in our sum is zero and we don't do anything.
         * Otherwise, then we should add n1 * 2^i.
         */
        if ((b & 1) != 0)
        {
            /* Recall that a = n1 * 2^i at this point, so we're adding
             * in the next term in the sum.
             */
            result = result + a;
        }

        /* To maintain that a = n1 * 2^i after i iterations, scale it
         * by a factor of two by left shifting one position.
         */
        a <<= 1;

        /* To maintain that b = n2 >> i after i iterations, shift it
         * one spot over.
         */
        b >>>= 1;
    }

    System.out.println(result);
}

希望这可以帮助!



 类似资料:
  • 问题内容: 在Java中,有什么方法可以得到2 的乘法的高半部分吗?即由于溢出而消失的部分。(因此128位结果的高64位) 我习惯于在命令执行以下操作的地方编写OpenCL代码:http : //www.khronos.org/registry/cl/sdk/1.0/docs/man/xhtml/mul_hi.html 由于OpenCL可以在我的CPU上有效地执行此操作,因此Java应该也可以执行

  • 我有一个Java BigDecimal表达式,如下所示: 哪里 BigDecimal totalCase = BigDecimal。零;BigDecimal totalPrep = BigDecimal。零; 我必须将totalPrep除以totalCase,结果乘以100,得到以%表示的结果值。66.6666666666666666666666666666666666667 假设总准备是二进制2

  • 考虑以下代码: 我可以理解Python(和其他语言)中的算术运算符,但我从来没有很好地理解过“按位”运算符。在上面的示例中(来自Python书籍),我理解左移位,但不理解其他两个。 此外,位运算符实际用于什么?我想举一些例子。

  • 问题内容: 我只是在玩Java。编写了这个小程序: 输出如下: 2147483647 -2 2147483645 -4 2147483643 -6 2147483641 -8 2147483639 -10 现在我很惊讶。我不知道如何解释这个输出。我知道我可以使用long代替大于整数的最大限制来处理值。但是我只想知道java如何计算这个? 问题答案: 我们需要分析结果的二进制内容: Integer.

  • 我使用SIMD创建了一个64位*64位到128位的函数。目前我已经使用SSE2(实际上是SSE4.1)实现了它。这意味着它同时生产两个64b*64b到128b的产品。同样的想法可以扩展到AVX2或AVX512,同时提供四个或八个64b*64到128b的产品。我的算法基于http://www.hackersdelight.org/hdcodetxt/muldws.c.txt 该算法执行一次无符号乘法

  • 问题内容: 考虑以下代码: 我可以用Python(和其他语言)理解算术运算符,但我对“按位”运算符却不太了解。在上面的示例(来自Python书)中,我了解了左移功能,但不了解其他两个。 另外,按位运算符实际上是用来做什么的?我会喜欢一些例子。 问题答案: 按位运算符是对多位值进行操作的运算符,但在概念上一次只能处理一位。 仅当其两个输入均为1时,才为1;否则为0。 如果其输入之一或全部为1,则为1