I'm new to Julia and was coding a bit for fun. My current project was creating code for checking whether a number is sublime or not. For context (and a bit of trivia I suppose), a sublime number n is defined by two qualities:

  1. the number of divisors (including n) is a perfect number
  2. the sum of the divisors (including n) is a perfect number (perfect numbers have the quality that the sum of their divisors - not including the number itself - add up to the number itself)

12 is a sublime number, and I suspect that is the reason I get the error message for most of its multiples. My code (seen below - I'm new to Julia so be prepared for inefficiences) works as it should for any other number.

The BoundsError message appears for every multiple of 12 except for 36, 72, 144, 288,... (so the 3rd, 6th, 12th, 24th, and I assume every multiple following that sequence afterwards). I'd be very interested to know why and very grateful if someone were able to help.

Here's the code:

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

Basically, I'm creating an array (called "ncheck") of length n with only zeroes, checking which numbers k < n result have a remainder of 0, updating the array to include those k, and deleting every 0.

Then I create an array "sumcheck" with length "divsum", meaning the sum of the divisors of n. I repeat the above process. Check what gives me a remainder of 0 and delete the remaining zeroes in the array.

The final array is "lcheck" with length "divnum", meaning the number of divisors of n. Same process as above, only those divisors with a remainder of 0 remain.

Finally, I check whether the sum of the entries in lcheck are equal to the length of ncheck and the sum of entries in sumcheck are equal to sum of divisors in n. If both are true, then I have a sublime number on my hands, if either one or both are false, I don't.

Here's the error for 12, which is a sublime number:

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

For comparison, here are the error messages for 24 and 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

I hope my information can provide some clues on to solving the current problem!

2

There are 2 best solutions below

4
Mark On

The issue is that in Julia, & is bitwise and, whereas && is the boolean 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

Sidenote: the code can be reduced to:

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
1
Dan Getz On

Another way to check for sublimeness:

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))...))
  ))

And we have:

julia> sublime(12)
true

julia> sublime(13)
false

This method is more Julian because it integrates with relevant package (and thus when factorization algo is improved, so will this code). Also care is taken to calculate factor(k) once, since this is the resource consuming operation. Needless to say, the exponentially larger divisor set is not realized.

The sublimeness of this solution is for the reader to decide.

P.S. Using number theory facts (I haven't looked into), more optimization should be possible for most numbers.