Julia编写的sublime number检测代码对12的多数倍数报错求因
Sublime Number检测代码的BoundsError问题
问题背景
Sublime Number的定义需满足两个条件:
- 其正约数(含自身)的个数是一个完美数;
- 其正约数(含自身)的和是一个完美数。
(完美数定义:除自身外的正约数之和等于自身)
12本身是Sublime Number,但我的代码对它的多数倍数会报BoundsError,仅36、72、144、288……这类倍数(第3、6、12、24个倍数及后续同序列倍数)能正常运行,其他倍数均报错,代码对其他数字运行正常,求分析原因。
代码实现
function sublime(n) ncheck = zeros(Int64, n) k = 1 for k = 1:n if rem(n,k) == 0 ncheck[k] = k else #do nothing end end ncheck = filter!(x -> x != 0, ncheck) divsum = sum(ncheck) sumcheck = zeros(Int64, divsum) for k = 1:(divsum-1) if rem(divsum, k) == 0 sumcheck[k] = k else #do nothing end end sumcheck = filter!(x -> x != 0, sumcheck) divnum = size(ncheck,1) lcheck = zeros(Int64, divnum) for k = 1:(divnum-1) if rem(divnum, k) == 0 lcheck[k] = k else #do nothing end end lcheck = filter!(x -> x != 0, lcheck) if sum(lcheck) == divnum & sum(sumcheck) == divsum println("y") else println("n") end end
代码逻辑说明
- 创建长度为
n的全零数组ncheck,遍历筛选出n的所有正约数并移除零元素; - 计算约数和
divsum,创建长度为divsum的数组sumcheck,筛选divsum的所有真约数; - 计算约数个数
divnum,创建长度为divnum的数组lcheck,筛选divnum的所有真约数; - 判断
lcheck的和是否等于divnum(即divnum是完美数)、sumcheck的和是否等于divsum(即divsum是完美数),以此判定n是否为Sublime Number。
错误信息
运行sublime(12)的错误
sublime(12) ERROR: BoundsError: attempt to access 12-element Vector{Int64} at index [14] Stacktrace: [1] setindex! @ .\array.jl:969 [inlined] [2] sublime(n::Int64) @ Main .\REPL[49]:19 [3] top-level scope @ REPL[78]:1
运行sublime(24)的错误
sublime(24) ERROR: BoundsError: attempt to access 24-element Vector{Int64} at index [30] Stacktrace: [1] setindex! @ .\array.jl:969 [inlined] [2] sublime(n::Int64) @ Main .\REPL[49]:19 [3] top-level scope @ REPL[80]:1
运行sublime(48)的错误
sublime(48) ERROR: BoundsError: attempt to access 48-element Vector{Int64} at index [62] Stacktrace: [1] setindex! @ .\array.jl:969 [inlined] [2] sublime(n::Int64) @ Main .\REPL[49]:19 [3] top-level scope @ REPL[82]:1
错误原因分析
从错误信息能直接看出,问题出在尝试访问长度为n的数组时用了大于n的索引(比如sublime(12)中用索引14访问12元素数组),结合栈追踪定位到sumcheck[k] = k这一行。
核心问题:你提供的代码里sumcheck = zeros(Int64, divsum)的写法是正确的,但大概率是代码复制时的格式问题——你写的x ->是HTML转义字符,而非Julia原生的箭头->,这会导致filter!函数无法正确过滤ncheck数组,使得ncheck仍保留原长度n,后续即使divsum计算正确,也可能因解释器异常导致sumcheck数组被错误设置为长度n,最终触发索引越界。
另外还有两个可优化的点:
- Julia中逻辑与应该用
&&而非&,&是按位与运算符,虽然这里结果可能一致,但不符合代码语义; - 无需创建全零数组再过滤,直接用列表推导式收集约数更高效,能减少出错概率。
修正后的代码示例
# 生成所有正约数 function get_divisors(n) return [k for k in 1:n if rem(n, k) == 0] end # 判断是否为完美数 function is_perfect(m) if m <= 1 return false end # 计算真约数和(不包含自身) proper_sum = sum(k for k in 1:m-1 if rem(m, k) == 0) return proper_sum == m end # 判断是否为Sublime Number function sublime(n) divs = get_divisors(n) div_count = length(divs) div_sum = sum(divs) if is_perfect(div_count) && is_perfect(div_sum) println("y") else println("n") end end
内容的提问来源于stack exchange,提问作者QuarkbällchenAddict
相关产品推荐
相关产品推荐

