奇怪的是,我用于检查一个数字是否是崇高数字的代码对于 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?

提问人:QuarkbällchenAddict 提问时间:9/5/2023 更新时间:9/6/2023 访问量:54

问:

我是 Julia 的新手,为了好玩而编码。我目前的项目是创建代码来检查一个数字是否崇高。对于上下文(我想还有一点琐事),一个崇高的数字 n 由两个品质定义:

  1. 除数(包括 n)是一个完美的数字
  2. 除数(包括 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 IndexOutofBoundsException

评论


答:

1赞 Mark 9/5/2023 #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

评论

0赞 QuarkbällchenAddict 9/5/2023
哦,是的,我最初也是这么认为的。我的意思是,我的代码中有单&而不是双&&,但我记得测试了差异,它没有任何区别。所以我不认为这是问题所在,除非我误解了什么......
0赞 Mark 9/5/2023
你是。再试一次!
0赞 QuarkbällchenAddict 9/6/2023
好的,会的,谢谢!
0赞 QuarkbällchenAddict 9/6/2023
哦,刚刚看到,也非常感谢代码改进:)
1赞 Dan Getz 9/6/2023 #2

检查崇高的另一种方法:

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. 使用数论事实(我没有研究过),对于大多数数字来说,应该可以进行更多的优化。

评论

0赞 QuarkbällchenAddict 9/6/2023
谢谢!然后把我的脑袋包裹在那个代码上