提问人:QuarkbällchenAddict 提问时间:9/5/2023 更新时间:9/6/2023 访问量:54
奇怪的是,我用于检查一个数字是否是崇高数字的代码对于 12(一个崇高数字本身)的倍数失败了。有谁知道为什么?
My code for checking whether a number is a sublime number or not curiously fails for multiples of 12 (a sublime number itself). Does anyone know why?
问:
我是 Julia 的新手,为了好玩而编码。我目前的项目是创建代码来检查一个数字是否崇高。对于上下文(我想还有一点琐事),一个崇高的数字 n 由两个品质定义:
- 除数(包括 n)是一个完美的数字
- 除数(包括 n)的总和是一个完美的数字 (完美数的质量是它们的除数之和(不包括数字本身)加起来就是数字本身)
12 是一个崇高的数字,我怀疑这就是我收到大多数倍数错误消息的原因。 我的代码(见下文 - 我是 Julia 的新手,所以要为效率低下做好准备)与任何其他数字一样工作。
除 36、72、144、288 外,每 12 的倍数都会出现 BoundsError 消息,...(所以第 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”),检查哪些数字 k < n 结果的余数为 0,更新数组以包含这些 k,并删除每个 0。
然后我创建一个长度为“divsum”的数组“sumcheck”,意思是 n 的除数之和。我重复上述过程。检查是什么给了我 0 的余数并删除数组中剩余的零。
最后一个数组是“lcheck”,长度为“divnum”,表示 n 的除数。与上述过程相同,只剩下余数为 0 的除数。
最后,我检查 lcheck 中条目的总和是否等于 ncheck 的长度,sumcheck 中的条目总和是否等于 n 中的除数之和。如果两者都是真的,那么我手上有一个崇高的数字,如果其中一个或两个都是假的,我就没有。
这是 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
为了进行比较,以下是 24 和 48 的错误消息:
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)
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
我希望我的信息能为解决当前问题提供一些线索!
答:
问题是在 Julia 中,& 是按位的,而 &
&
是布尔值 and
。
6 & 28 # equals 4, because the bitwise and of 110 and 11100 is 100 (i.e. 4 in decimal)
6 && 28 # equals ERROR: TypeError: non-boolean (Int64) used in boolean context
旁注:代码可以简化为:
is_perfect_number(n)= sum([i for i in 1:n-1 if n % i == 0]) == n
function is_sublime_number(n)
v = [i for i in 1:n if n % i == 0]
return is_perfect_number(sum(v)) && is_perfect_number(length(v))
end
评论
检查崇高的另一种方法:
using Primes # install package if needed
sumdivisors(n) =
prod((k^(v+1)-1)÷(k-1) for (k,v) in factor(n))
perfect(n) = sumdivisors(n) == 2n
sublime(k) =
all(perfect.(
prod.(zip((((k^(v+1)-1)÷(k-1), v+1) for (k,v) in factor(k))...))
))
我们有:
julia> sublime(12)
true
julia> sublime(13)
false
这种方法更像是朱利安式的,因为它与相关的包集成(因此,当因式分解算法得到改进时,这段代码也会得到改进)。此外,还要注意计算一次,因为这是消耗资源的操作。毋庸置疑,指数级更大的除数集没有实现。factor(k)
这个解决方案的崇高性是由读者决定的。
P.S. 使用数论事实(我没有研究过),对于大多数数字来说,应该可以进行更多的优化。
评论