获取IndexError:字符串索引超出python问题的范围

2024-09-30 03:23:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我要解决的问题是求两个大数字的和,其中的数字以字符串形式给出。 算法是:

  1. 将两个字符串反转
  2. 继续从第0个索引(反向字符串)到较小字符串的结尾逐个添加数字,将总和%10追加到结果的结尾,并将进位作为总和/10进行跟踪
  3. 最后扭转结果

这就是我尝试的代码:

def stringadd(s1, s2):
    s1 = s1[::-1]
    s2 = s2[::-1]
    
    m = len(s1)
    n = len(s2)
    carry = 0
    s = ""
    if len(s1) > len(s2):
        temp = s2
        s2 = s1
        s1 = temp
    for i in range(m):
        su, = (ord(s1[i]) - 48) + (ord(s2[i]) - 48) + carry
        s += chr(sum % 10 + 48)
        carry = int(sum / 10)
        
    for i in range(m, n):
        sum = (ord(s2[i]) - 48) + carry
        s += chr(sum % 10 + 48)
        carry = int(sum / 10)
        i += 1
    if carry:
        s += chr(carry + 48)
    s = s[::-1]
    return s


print(stringadd("32134", "23456782"))

我在第17行得到一个字符串索引超出范围错误,这是

sum = (ord(s1[i]) - 48) + (ord(s2[i]) - 48) + carry

Tags: 字符串forlenif结尾数字tempsum
2条回答

我试着运行代码,当我以print(stringadd("32134","23456782"))的形式发送输入时,我确实得到了正确的答案,但是当我将其更改为print(stringadd("23456782", "32134"))时,我遇到了错误。这是因为您正在使用mn进行循环,但在某些情况下(当len(s1)>len(s2))您正在交换s1s2

您应该在交换之后取s1s2的值。这将修复代码。请在下面找到正确的代码

def stringadd(s1,s2):
    
    s1=s1[::-1]
    s2=s2[::-1]
    
    
    carry=0
    s=""
    
    if len(s1)>len(s2):
        
        temp=s2
        s2=s1
        s1=temp
    
    # Value of m and n taken after interchaning
    m=len(s1)
    n=len(s2)
    
    for i in range(m):
        sum=(ord(s1[i])-48)+(ord(s2[i])-48) +carry
        s+=chr(sum%10 +48)
        carry=int(sum/10)
        
    for i in range(m,n):
        sum=(ord(s2[i])-48)+carry
        s+=chr(sum%10 +48)
        carry=int(sum/10)

    if(carry):
        s+=chr(carry+48)
    s=s[::-1]
    return s


print(stringadd("23456782", "32134"))

您还可以改变以下几个方面:

  1. 不要使用sum作为变量,因为它是保留关键字
  2. 从代码中删除i += 1,因为它在forloop中没有任何作用

希望这能回答你的问题

有几件事:

  • 在交换s1和s2之前,您需要计算mn的长度,因此它们不一定再匹配
  • 在for循环中有一个i+=1,它什么都不做
  • 您正在使用sum作为变量名,隐藏内置的sum函数

我建议改写如下:

def stringadd(s1, s2):
    shorter, longer = (x[::-1] for x in sorted((s1, s2), key=len))
    carry = 0
    result = ""

    for i in range(len(shorter)):
        s = (ord(shorter[i]) - 48) + (ord(longer[i]) - 48) + carry
        result += chr((s % 10) + 48)
        carry = int(s / 10)

    for i in range(len(shorter), len(longer)):
        s = (ord(longer[i]) - 48) + carry
        result += chr(s % 10 + 48)
        carry = int(s / 10)

    if (carry):
        result += chr(carry + 48)

    return result[::-1]


if __name__ == '__main__':
    print(stringadd("32134", "23456782"))
    assert(32134 + 23456782 == int(stringadd("32134", "23456782")))
    print(stringadd("999", "9"))
    assert(999 + 9 == int(stringadd("999", "9")))

其中一些优势:

  • 更具描述性的变量名
  • 使用len(shorter)len(longer)而不是nm来明确其含义

您甚至可以用ord("0")替换神奇常数48,以更清楚地说明该数字的作用。为了好玩,我们还可以使用更实用的风格:

from functools import reduce
def stringadd2(s1, s2):
    # Make s1 and s2 the same length by appending 0s to the reversed string,
    # then pair them up.
    digits = zip(s1[::-1] + "0" * (max(len(s1), len(s2)) - len(s1)),
                 s2[::-1] + "0" * (max(len(s1), len(s2)) - len(s2)))

    # The function for our reducer which has state in part and gets each pair
    # of digits in x iteratively.
    def add(part, x):
        s = (ord(x[0]) - ord("0")) + (ord(x[1]) - ord("0")) + part[1]
        return part[0] + chr((s % 10) + ord("0")), int(s / 10)

    result, carry = reduce(add, digits, ("", 0))
    if carry:
        result += chr(ord("0") + carry)

    return ''.join(result[::-1])

相关问题 更多 >

    热门问题