输入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,属于无效输入。
修复方案
- 提前校验无效输入:在函数开头检查输入是否为全相同数字,直接返回标记提示错误。
- 补全分支逻辑:在加减部分增加
else分支,处理a_num == d_num的情况。 - 简化冗余代码:把手动转数字的循环去掉,直接用
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
相关产品推荐
相关产品推荐

