如何将代表十进制数字的字符串转换成代表其二进制形式的字符串?

问题描述

让我们以字符串s =“ 556852144786”为例,该字符串代表十进制数字n = 556852144786,是否有直接算法将其转换为s1 =“ 101100101110 .....”,而101100101110是n的二进制表示形式?

解决方法

我假设您正在寻找一种直接对字符串进行运算的算法,而不是转换为目标语言支持的整数并使用它们?

有多种方法可以做到这一点。这里有两个,不过如果您斜视一下,它们几乎是相同的算法。

方法1:将十进制字符串重复除以二

在此方法中,我们将原始十进制字符串重复除以2(使用十进制算术),并跟踪余数:这些余数以相反的顺序为您提供结果的位。 这是Python中该算法的外观。它缺少is_nonzerodivide_by_two的定义。我们稍后会提供这些。

def dec_to_bin(s):
    """
    Convert decimal string s to binary,using only string operations.
    """
    bits = ""
    while is_nonzero(s):
        s,bit = divide_by_two(s)
        bits += bit
    # The above builds up the binary string in reverse.
    return bits[::-1]

该算法以相反的顺序生成位,因此我们需要进行最后的反转以给出生成的二进制字符串。

divide_by_two函数采用一个十进制字符串s,并返回一个表示商s / 2的新十进制字符串,以及其余的字符串。其余部分为单个位,再次表示为字符串-"0""1"。它遵循通常的逐位数字教学的从左到右的划分方法:每个步骤都涉及将一个数字以及前一步带来的进位除以2。这是该功能:

def divide_by_two(s):
    """
    Divide the number represented by the decimal string s by 2,giving a new decimal string quotient and a remainder bit.
    """
    quotient = ""
    bit = "0"
    for digit in s:
        quotient_digit,bit = divide_digit_by_two(bit,digit)
        quotient += quotient_digit
    return quotient,bit

我们只需要定义divide_digit_by_two,它需要用一位数字加上几十个进位位,然后除以2得到一位数商和一位余数。此时,所有输入和输出都是长度为一的字符串。在这里,我们作弊并使用了整数算法,但是只有20种可能的不同输入组合,因此我们可以轻松地使用查找表。

def divide_digit_by_two(bit,digit):
    """
    Divide a single digit (with tens carry) by two,giving
    a digit quotient and a single bit remainder.
    """
    digit,bit = divmod(int(bit) * 10 + int(digit),2)
    return str(digit),str(bit)

您可以将divide_digit_by_two视为原始算术运算,它以不同的底数交换两位数字:它将以20形式表示的小于10 * bit + digit的非负整数转换为相同的值以2 * digit + bit的形式表示。

我们仍然缺少一个定义:is_nonzero的定义。当且仅当十进制字符串完全由零组成时,它才表示零。这是一个快速的Python测试。

def is_nonzero(s):
    """
    Determine whether the decimal string s represents zero or not.
    """
    return s.strip('0') != ''

现在我们已经准备就绪,可以测试:

>>> dec_to_bin("18")
'10010'
>>> dec_to_bin("556852144786")
'1000000110100110111110010110101010010010'
>>> format(556852144786,'b')  # For comparison
'1000000110100110111110010110101010010010'

方法2:将二进制字符串重复乘以10

这是第一种方法的一种变体:代替重复的除法,我们逐位处理传入的十进制字符串(从左到右)。我们从一个代表值0的空二进制字符串开始,每次处理一个数字时,我们都要乘以10(以二进制表示),然后再加上该数字表示的值。和以前一样,最方便的是按小端顺序(最低位在先)构建二进制字符串,然后在末尾反转以得到传统的大端表示。这是顶级功能:

def dec_to_bin2(s):
    """
    Convert decimal string s to binary,using only string operations.

    Digit-by-digit variant.
    """
    bits = ""
    for digit in s:
        bits = times_10_plus(bits,digit)
    return bits[::-1]

times_10_plus函数的工作是获取一个二进制字符串和一个数字,并生成一个新的二进制字符串,该字符串表示将原始值乘以10,然后将二进制数字的值相加的结果。看起来像这样:

def times_10_plus(bits,digit):
    """
    Multiply the value represented by a binary string by 10,add a digit,and return the result as a binary string.
    """
    result_bits = ""
    for bit in bits:
        digit,result_bit = divide_digit_by_two(bit,digit)
        result_bits += result_bit
    while digit != "0":
        digit,result_bit = divide_digit_by_two("0",digit)
        result_bits += result_bit
    return result_bits

请注意,我们之前使用的是完全相同的算术基元divide_digit_by_two,但现在我们考虑的略有不同:它将一位乘以十,再加上一个进位数字,并将其与新的进位数字一起转换为新的位(结果的最低有效位)。

效率说明

为了清楚起见,我保留了一些Python级别的低效率。特别是,在构建字符串时,构建位或数字的列表,然后直接在末尾使用str.join操作进行连接会更有效。还要注意,根据实现语言的不同,在原位置修改数字字符串或位字符串可能比在每个步骤中生成新字符串更有意义。我将必要的更改留给您。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...