查找整数N中连续子串构成的pronic number的程序测试用例失败问题排查
问题回顾
你需要实现一个程序,输入整数N(范围1 <= N <= 10^20),输出所有由N中连续数字序列构成的pronic整数(即可以表示为n*(n+1)的数),要求按出现顺序输出。目前你的代码仅通过3个测试用例,还有1个测试用例失败,我们来逐一排查可能的问题。
题目关键信息
pronic整数定义:可以表示为
n*(n+1)的形式,例如0=0×1、6=2×3、42=6×7等。
输入输出要求:输出连续子串对应的pronic数,按出现顺序排列,用空格分隔。
示例参考
示例1
- 输入:
93042861 - 输出:
930 30 0 42 2 6 - 解释:930=30×31,30=5×6,0=0×1,42=6×7,2=1×2,6=2×3
示例2
- 输入:
247025123524 - 输出:
2 702 0 2 12 2 2352 2
你的当前代码
import math def is_pronic(number): if number==0: return True x=int(math.sqrt(number)) return x*(x+1)==number def f_pronic_numbers(number): char=str(number) length=len(char) # pronic_number=[] for i in range(length): for j in range(i+1,length+1): if is_pronic(int(char[i:j])) and (char[i:j]==str(int(char[i:j]))): print(char[i:j],end=" ") n=int(input()) f_pronic_numbers(n)
可能的问题排查与修复方案
1. 输出末尾的多余空格(格式错误)
你的代码使用print(char[i:j], end=" "),会导致输出结果的末尾多一个空格。很多在线判题系统(OJ)对输出格式要求严格,这种多余空格会被判定为格式错误,直接导致测试用例失败。
修复方法:先收集所有符合条件的结果到列表中,最后用" ".join()拼接输出,这样不会产生末尾空格:
def f_pronic_numbers(number): char = str(number) length = len(char) pronic_numbers = [] # 用列表收集结果 for i in range(length): for j in range(i+1, length+1): substr = char[i:j] num = int(substr) if is_pronic(num) and (substr == str(num)): pronic_numbers.append(substr) print(" ".join(pronic_numbers)) # 用join拼接,无末尾空格
2. math.sqrt的精度丢失问题
当处理非常大的pronic数(比如接近10^20的数)时,math.sqrt()返回的浮点数可能存在精度误差,导致x=int(math.sqrt(number))得到的数值比实际正确值小1,进而x*(x+1)不等于原数,错误地判定该数不是pronic数。
比如,假设输入包含99999999999999999990(即9999999999 × 10000000000),math.sqrt()可能返回9999999998.999999,转成整数后是9999999998,此时9999999998 × 9999999999不等于原数,导致漏判。
修复方法:
- 如果你使用Python 3.8+,可以改用
math.isqrt(),它会返回整数的平方根(向下取整),精度更高:
def is_pronic(number): if number == 0: return True x = math.isqrt(number) return x * (x + 1) == number
- 兼容低版本Python的话,可以额外检查
x+1的情况,覆盖精度误差的可能:
def is_pronic(number): if number == 0: return True x = int(math.sqrt(number)) # 检查x和x+1两种情况,避免精度误差 return x*(x+1) == number or (x+1)*(x+2) == number
3. 前导零的处理验证
你的代码中char[i:j]==str(int(char[i:j]))的判断是为了过滤带前导零的多位数子串(比如02会被排除,因为int("02")=2,str(2)="2"不等于原串)。这符合题目示例的输出逻辑(示例中没有出现带前导零的多位数输出),所以这个判断是合理的,应该不是问题所在。
修复后的完整代码
import math def is_pronic(number): if number == 0: return True x = math.isqrt(number) # 优先用isqrt保证精度 return x * (x + 1) == number def f_pronic_numbers(number): char = str(number) length = len(char) pronic_numbers = [] for i in range(length): for j in range(i+1, length+1): substr = char[i:j] num = int(substr) if is_pronic(num) and (substr == str(num)): pronic_numbers.append(substr) print(" ".join(pronic_numbers)) n = int(input()) f_pronic_numbers(n)
这个版本应该能解决大部分可能的测试用例失败问题,尤其是格式错误和大数精度问题。
备注:内容来源于stack exchange,提问作者Nishanth Tamil

