对于大于2 ^ 64的数字,检查数是2的幂,执行手动除法

时间:2016-06-11 10:12:02

标签: java string character division

我正在尝试检查一个数字(输入为String)是否为2的幂。问题是该数字可能大于2^64(长期限制长度)。如果我将它存储在double中,那么我就不能对它进行二进制操作(因此技巧v & (v - 1) == 0不起作用)。这是我偶然发现的解决方案:

public class Solution {
    public int power(String A) {

        String dividend = A;
        StringBuilder str;

        if (A == null || A.length() == 0)
            return 0;

        if (A.length() == 1 && A.charAt(0) == '0')
            return 0;

        while (dividend.length() > 0 && !dividend.equalsIgnoreCase("2")) {
            str = new StringBuilder();
            int carry = 0;
            int n = dividend.length();

            if (n > 0) {
                int num = dividend.charAt(n - 1) - '0';

                if (num % 2 == 1)
                    return 0;
            }

            for (int i = 0; i < n; i++) {

                char c = (char) (dividend.charAt(i) - '0');
                int res = c + 10 * carry;

                c = (char) (res / 2 + '0');
                carry = res % 2;

                str.append(c);
            }

            if (str.charAt(0) == '0')
                str.deleteCharAt(0);

            dividend = str.toString();
        }

        return 1;

    }

}

我在理解解决方案时遇到了问题。如果数字是奇数,则完成第一次检查。我在理解在这个问题中完成的手动除法的实现方面遇到了问题(尤其是涉及char和int的算术运算)。我得到'0' == 48并从字符中减去'0'将其转换为整数值。任何人都可以向我解释这个分区操作是如何实现的吗?谢谢!

3 个答案:

答案 0 :(得分:0)

理解此实现的最简单方法是进行纸笔测试。我将跳过你理解的部分,只关注最后一个for循环。

让我们以"50"作为示例输入。从左侧开始,循环以字符顺序逐步执行String。因此,处理的第一个字符是'5'。如您所知,5很奇怪。这意味着我们必须&#34;携带&#34;进入下一个部门的东西。 5 / 2的结果是2。此2将是该部门结果的第一位数字。请注意,如果我们撤消我们的步骤,我们会得到2 * 2,即4。这就是我们必须携带一些东西的原因(1缺失,因为5 - 41)。您可能会注意到,如果除以2,则可以携带0(无)或1(当且仅当被除数为奇数时)。

现在转到下一个数字,即0。我们必须将最后一个部门的1带到此步骤。由于我们向左移动了一位数字,因此在此步骤中,previos步骤中的1变为10。我们将#34;向下移动了一个数量级,因此我们必须将进位部分乘以10。这意味着我们计算(0 + (1 * 10)) / 2,即10 / 2 = 5。此5是结果的第二个数字。由于股息是均匀的,我们不需要继续分红。

因此,最终输出为"25",正如预期的那样。

答案 1 :(得分:0)

    str = new StringBuilder();
    int carry = 0;
    int n = dividend.length();

    if (n > 0) {
        int num = dividend.charAt(n - 1) - '0';

分开输入。它取字符串末尾的字符,并从该值取值&#39; 0&#39; http://www.asciitable.com/ - 对于&#39; 0&#39;它是48.所以它给出了那个小数的值,没有任何解析。

        if (num % 2 == 1)
            return 0;
    }

接下来for循环将divided除以2。这是通过辅助每个数字来完成的。从第一个到最后一个。下一次迭代从prev获得值。

    for (int i = 0; i < n; i++) {

        char c = (char) (dividend.charAt(i) - '0');

如前所述 - 它&#39; c&#39;是带十进制值的字节。

        int res = c + 10 * carry;

&#39; RES&#39;也随身携带。

        c = (char) (res / 2 + '0');

特殊条目的划分在这里完成。添加&#39; 0&#39;是简单的转换为字符/字符串,

        carry = res % 2;

请注意,我们将从头开始,而不是从头开始。所以随身携带 到下一次迭代是模数。

        str.append(c);
    }

    if (str.charAt(0) == '0')
        str.deleteCharAt(0);

只需删除前导零

即可
    dividend = str.toString();

转换回字符串,再次调用除法。

答案 2 :(得分:0)

//试试这个!

    double n = scanner.nextInt();

    while (n > 1) {
        n = n / 2;
    }
    System.out.println(n);
    if (n == 1)
        System.out.println("true");
    else
        System.out.println("false");