You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

输入repdigit触发UnboundLocalError,Kaprekar's Constant计算代码故障排查

Kaprekar常数计算代码的Repdigit输入崩溃问题排查

我写了一段计算Kaprekar常数(6174)及迭代次数的代码,输入非重复数字(比如1234)时运行正常,但输入全相同数字(比如7777这类repdigit)时,会抛出UnboundLocalError: local variable referenced before assignment错误导致崩溃,求帮忙排查问题。代码如下:

# take user input
# if number has less than 4 digits, add leading zeroes
# make number a str and convert to two lists
# one list will be sorted in descending order and the other in ascending
# subtract smaller from bigger
# repeat step 2 until you reach 6174
# use loops

### DEFINE A FUNCTION ###
def k_c(n):
    num_list = [n]
    ### WHILE LOOP TO ADD LEADING ZEROS IF NEEDED ###
    while len(n) != 4:
        n = "0" + n

    d_list = list(n)
    d_list.sort(reverse=True)  # converts to descending list
    a_list = list(n)
    a_list.sort()  # converts to ascending list
    d_num = []
    a_num = []
    ### CONVERT TO INT ###
    for i in d_list:
        d_num.append(int(i))
    for i in a_list:
        a_num.append(int(i))
    d_num = "".join(d_list)
    a_num = "".join(a_list)
    d_num = int(d_num)
    a_num = int(a_num)

    if a_num > d_num:
        new_num = a_num - d_num
        num_list.append(new_num)
    elif d_num > a_num:
        new_num = d_num - a_num
        num_list.append(new_num)

    count = 1

    if len(str(new_num)) != 4:
        new_num = "0" + str(new_num)

    while new_num != 6174:  # will repeat until 6174 is reached
        ### SEPARATE INTO 2 LISTS ###
        d_list = list(str(new_num))
        d_list.sort(reverse=True)  # converts to descending list
        a_list = list(str(new_num))
        a_list.sort()  # converts to ascending list
        d_num = []
        a_num = []
        for i in d_list:
            d_num.append(int(i))
        for i in a_list:
            a_num.append(int(i))
        d_num = "".join(d_list)
        a_num = "".join(a_list)
        d_num = int(d_num)
        a_num = int(a_num)

        ### SUBTRACT SMALLER LIST NUMBER FROM LARGER LIST NUMBER ###
        if a_num > d_num:
            new_num = a_num - d_num
            num_list.append(new_num)
            count += 1
        elif d_num > a_num:
            new_num = d_num - a_num
            num_list.append(new_num)
            count += 1
    return num_list, count


num = input("Enter a four-digit integer: ")
k_numbers, iterations = k_c(num)  # establishing variables

for i in range((len(k_numbers))):  # lopping through each new number used to calculate Kaprekar's constant
    if i != (len(k_numbers) - 1):
        print(k_numbers[i], end=" > ")
    else:
        print(k_numbers[i])

print(f"{num} reaches 6174 via Kaprekar's routine in {iterations} iterations")

问题根源

当输入全相同数字时,比如7777,排序后的升序和降序数字完全一致,a_num和d_num相等。但你的代码里只写了if a_num > d_num和elif d_num > a_num两个分支,完全没处理相等的情况,导致new_num变量根本没被定义,后续代码一引用它就触发未绑定变量的错误。

另外,Kaprekar规则本身要求输入的四位数不能是全相同数字——这类数字相减会得到0000,永远到不了6174,属于无效输入。

修复方案

  1. 提前校验无效输入:在函数开头检查输入是否为全相同数字,直接返回标记提示错误。
  2. 补全分支逻辑:在加减部分增加else分支,处理a_num == d_num的情况。
  3. 简化冗余代码:把手动转数字的循环去掉,直接用join加int转换,用zfill(4)简化补前导零的操作。

修复后的完整代码

### 计算Kaprekar常数的函数 ###
def k_c(n):
    num_list = [n]
    # 检查是否为全相同数字(无效输入)
    if len(set(n)) == 1:
        return num_list, -1  # 用-1标记无效输入

    # 补前导零至4位
    n = n.zfill(4)

    # 生成降序和升序数字
    d_num = int("".join(sorted(n, reverse=True)))
    a_num = int("".join(sorted(n)))

    # 计算第一次相减结果
    if a_num > d_num:
        new_num = a_num - d_num
    elif d_num > a_num:
        new_num = d_num - a_num
    else:
        new_num = 0
    num_list.append(new_num)
    count = 1

    # 转成带前导零的字符串,方便后续处理
    new_num_str = str(new_num).zfill(4)

    # 迭代直到得到6174或0000
    while new_num_str != "6174":
        if new_num_str == "0000":
            break
        
        # 重新生成降序和升序数字
        d_num = int("".join(sorted(new_num_str, reverse=True)))
        a_num = int("".join(sorted(new_num_str)))

        # 计算相减结果
        if a_num > d_num:
            new_num = a_num - d_num
        elif d_num > a_num:
            new_num = d_num - a_num
        else:
            new_num = 0
        num_list.append(new_num)
        count += 1
        new_num_str = str(new_num).zfill(4)
    
    return num_list, count


# 用户交互部分
num = input("请输入一个四位整数:")
k_numbers, iterations = k_c(num)

# 打印迭代过程
for i in range(len(k_numbers)):
    if i != len(k_numbers) - 1:
        print(k_numbers[i], end=" > ")
    else:
        print(k_numbers[i])

# 打印结果
if iterations == -1:
    print(f"{num}是全相同数字,不符合Kaprekar规则的输入要求")
else:
    print(f"{num}通过Kaprekar迭代法到达6174共需{iterations}次迭代")

关键修改点

  • 用len(set(n)) == 1快速判断是否为全相同数字(集合去重后只剩一个元素)
  • 用zfill(4)自动补前导零,替代原来的while循环
  • 补全了a_num == d_num的分支,避免变量未定义
  • 增加了0000的判断,提前终止无效迭代
  • 优化了数字转换逻辑,去掉冗余的循环操作
  • 中文交互提示更友好

内容的提问来源于stack exchange,提问作者elguero

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:30:56