【问题标题】:checking number is power of 2 for numbers greater than 2^64, implementation of manual division检查大于 2^64 的数字是 2 的幂,实现手动除法
【发布时间】:2016-10-12 06:19:59
【问题描述】:

我正在尝试检查一个数字(输入为 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' 将其转换为整数值。谁能向我解释一下这个除法操作是如何在这里实施的?谢谢!

【问题讨论】:

    标签: java string character division


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:
          str = new StringBuilder();
          int carry = 0;
          int n = dividend.length();
      
          if (n > 0) {
              int num = dividend.charAt(n - 1) - '0';
      

      除以输入。它在字符串的末尾取字符,并从该值取值 '0' http://www.asciitable.com/ - 对于“0”,它是 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');
      

      和以前一样-它'c'是带有十进制值的字节。

              int res = c + 10 * carry;
      

      'res' 也有进位。

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

      特定条目的划分在此处完成。添加'0'是简单的转换为字符/字符串,

              carry = res % 2;
      

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

              str.append(c);
          }
      
          if (str.charAt(0) == '0')
              str.deleteCharAt(0);
      

      只需删除前导零

          dividend = str.toString();
      

      转回字符串,再次调用divide。

      【讨论】:

        【解决方案3】:

        //试试这个!

            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");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-10
          • 1970-01-01
          • 1970-01-01
          • 2017-10-27
          • 1970-01-01
          • 2014-11-05
          相关资源
          最近更新 更多