c++ - 给定一个巨大的整数字符串,检查它是否是 2 的幂

标签 c++ algorithm

这个数字很大(无法容纳在 C++ 中的 unsigned long long int 的范围内)。我们如何检查?

给出了一个解决方案here但这没有多大意义。 这里的解决方案尝试将大数(表示为字符串)重复除以 2,但我不确定我是否理解结果是如何一步步达到的。 有人可以解释一下或提出更好的解决方案吗? 我们不能使用任何外部库。

这是示例代码:

int isPowerOf2(char* str) 
{ 
    int len_str = strlen(str); 

    // sum stores the intermediate dividend while 
    // dividing. 
    int num = 0; 

    // if the input is "1" then return 0 
    // because 2^k = 1 where k >= 1 and here k = 0 
    if (len_str == 1 && str[len_str - 1] == '1') 
        return 0; 

    // Divide the number until it gets reduced to 1 
    // if we are successfully able to reduce the number 
    // to 1 it means input string is power of two if in  
    // between an odd number appears at the end it means  
    // string is not divisible by two hence not a power 
    // of 2. 
    while (len_str != 1 || str[len_str - 1] != '1') { 

        // if the last digit is odd then string is not 
        // divisible by 2 hence not a power of two  
        // return 0. 
        if ((str[len_str - 1] - '0') % 2 == 1) 
            return 0; 

        // divide the whole string by 2. i is used to 
        // track index in current number. j is used to 
        // track index for next iteration. 
        for (int i = 0, j = 0; i < len_str; i++) { 
            num = num * 10 + str[i] - '0'; 

            // if num < 2 then we have to take another digit 
            // to the right of A[i] to make it bigger than  
            // A[i]. E. g. 214 / 2 --> 107 
            if (num < 2) { 

                // if it's not the first index. E.g 214 
                // then we have to include 0. 
                if (i != 0)  
                    str[j++] = '0';                 

                // for eg. "124" we will not write 064 
                // so if it is the first index just ignore 
                continue; 
            } 

            str[j++] = (int)(num / 2) + '0'; 
            num = (num) - (num / 2) * 2; 
        } 

        str[j] = '\0'; 

        // After every division by 2 the  
        // length of string is changed. 
        len_str = j; 
    } 

    // if the string reaches to 1 then the str is 
    // a power of 2. 
    return 1; 
} 

我试图理解 while 循环中的过程。我知道有评论,但它们并没有真正帮助我理清逻辑。

最佳答案

让我们从弄清楚如何减半“字符串数字”开始。我们将从 128 开始作为示例。您可以依次将每个数字减半(从左边开始),请记住奇数会影响右边的数字(a)。因此,对于 128 中的 1,将其减半得到零,但由于它是奇数,因此应将 5 保留在存储中以添加到其右侧的数字(一旦减半):

128
 v
028

然后按如下方式将 2 减半(加回已存储的 5):

028
 v
018
 v
068

因为这并不奇怪,所以我们不为下一位存储 5,所以我们将 8 减半,如下所示:

068
 v
064

您还可以通过去掉任何前导零来简化操作。从中,您可以看到它正确地将 128 减半得到 64

要查看一个数是否是 2 的幂,您只需保持将它减半,直到恰好达到 1。但是,如果在任何时候你得到一个奇数(以 {1, 3, 5, 7, 9} 中的数字结尾的东西),前提是它不是个位数 1 ),它不是二的幂。

例如,以下 Python 3 代码说明了这个概念:


import re, sys

# Halve a numeric string. The addition of five is done by
# Choosing the digit from a specific set (lower or upper
# digits).    

def half(s):
    halfS = ''                              # Construct half value.
    charSet = '01234'                       # Initially lower.
    for digit in s:                         # Digits left to right.
        if digit in '13579':                # Select upper for next if odd.
            nextCharSet = '56789'
        else:
            nextCharSet = '01234'           # Otherwise lower set.
        halfS += charSet[int(digit) // 2]   # Append half value.
        charSet = nextCharSet               # And prep for next digit.

    while halfS[0] == '0':                  # Remove leading zeros.
        halfS = halfS[1:]

    return halfS

# Checks for validity.

if len(sys.argv) != 2:
    print('Needs a single argument')
    sys.exit(1)

num = sys.argv[1]
if not re.match('[1-9][0-9]*', num):
    print('Argument must be all digits')
    sys.exit(1)

print(num)
while num != '1':
    if num[-1:] in '13579':
        print('Reached odd number, therefore cannot be power of two')
        sys.exit(0)
    num = half(num)
    print(num)

print('Reached 1, was therefore power of two')

使用各种(数字)参数运行它会向您展示该过程,例如:

pax$ python ispower2.py 65534
65534
32767
Reached odd number, therefore cannot be power of two

pax$ python ispower2.py 65536
65536
32768
16384
8192
4096
2048
1024
512
256
128
64
32
16
8
4
2
1
Reached 1, was therefore power of two

(a) 以数字 34 为例。 3 的一半是 1.5,因此 1 可用于影响特定数字位置,但“一半"剩下的可以简单地通过将右边的数字减半后增加五来使用。因此,4 减半为 2,然后加上 5 得到 734 的一半是 确实 17

关于c++ - 给定一个巨大的整数字符串,检查它是否是 2 的幂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52677174/

相关文章:

algorithm - 将此算法命名为 : Comparing and interpolating points?

algorithm - 众包排名配对的最佳算法?

c++ - 编程测试/问题

C++ 代码比它的 C 等效代码慢?

c++ - 库和命名空间之间的关系是什么?

python - 在二维二进制矩阵中找到岛屿的数量

algorithm - 基于寄存器的编译器中递归函数的性能

c++ - 在 Windows 上安装 MongoDB C++ 驱动程序。

C++ hexfloat 编译时解析

algorithm - 事件图中的for循环