# Comparing Julia and Python for basic operations

**URL:** <https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087>\
**Category:** Performance\
**Created:** [July 22, 2021, 8:10am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087 "2021-07-22T08:10:45Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![daviddoij](https://avatars.discourse-cdn.com/v4/letter/d/87869e/32.png) [@daviddoij](https://discourse.julialang.org/u/daviddoij)\
**Post date:** [July 22, 2021, 8:10am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/1 "2021-07-22T08:10:45Z")

</div>

Hi there Julia community!,

I’m quite new to the language and I’m falling in love more and more with it every day 🙂

In order to improve my knowledge, I’m revisiting Project Euler problems, which I’ve done in Python, with Julia and, so far, Julia code is waaay faster than Python (who knew! :D)  
But I’m getting problems with the following problem that runs in 4.6 s while the Python version runs in 2.4 s. Both versions are almost identical

Julia version

```julia
function Problem12()
    #=
     The sequence of triangle numbers is generated by adding the natural
    numbers. So the 7th triangle number would be:
    1 + 2 + 3 + 4 + 5 + 6 + 7 = 28.

    The first ten terms would be:
    1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

    Let us list the factors of the first seven triangle numbers:

     1: 1
     3: 1,3
     6: 1,2,3,6
    10: 1,2,5,10
    15: 1,3,5,15
    21: 1,3,7,21
    28: 1,2,4,7,14,28

    We can see that 28 is the first triangle number to have over five divisors.

    What is the value of the first triangle number to have over five hundred
    divisors?
    =#

    function num_divisors(n)
        res = floor(sqrt(n))
        divs = []
        for i in 1:res
            if n%i == 0
                append!(divs,i)
            end
        end
        if res^2 == n
            pop!(divs)
        end
        return 2*length(divs)
    end

    triangle = 0
    for i in Iterators.countfrom(1)
        triangle += i
        if num_divisors(triangle) > 500
            return string(triangle)
        end
    end
end

```

Python version (for comparison)

```julia
import itertools
from math import sqrt, floor

# Returns the number of integers in the range [1, n] that divide n.
def num_divisors(n):
    end = floor(sqrt(n))
    divs = []
    for i in range(1, end + 1):
        if n % i == 0:
            divs.append(i)
    if end**2 == n:
        divs.pop()
    return 2*len(divs)

def compute():
    triangle = 0
    for i in itertools.count(1):
        # This is the ith triangle number, i.e. num = 1 + 2 + ... + i =
        # = i*(i+1)/2
        triangle += i
        if num_divisors(triangle) > 500:
            return str(triangle)

```

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [July 22, 2021, 8:33am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/2 "2021-07-22T08:33:06Z")

</div>

> [@daviddoij](#):
>
> ```julia
> res = floor(sqrt(n))
> 
> ```

One simple speed-up is to replace this line by `res = floor(Int, sqrt(n))`, as otherwise `floor` returns a `Float64`.

On a side note, I wonder if your `num_divisors` function is correct, as it returns `2` for `9` instead of `3` (unless I have the wrong definition of “divisors”). A fix could be to not `pop!` when `res^2 == n`, but instead to substract `1` to the returned result.

---

<div class="post-metadata">

**Author:** ![daviddoij](https://avatars.discourse-cdn.com/v4/letter/d/87869e/32.png) [@daviddoij](https://discourse.julialang.org/u/daviddoij)\
**Post date:** [July 22, 2021, 8:36am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/3 "2021-07-22T08:36:52Z")

</div>

Thx for your answer!  
I’ve made a couple of changes (I’m not interested in the divisors themselves, just in the number of them) and now the code runs in 0.12 s 😃

```julia
    function num_divisors(n)
        #res = floor(sqrt(n))
        res = floor(Int, sqrt(n))
        divs = 0#[]
        for i = 1:res
            if n % i == 0
                divs += 1
                #append!(divs, i)
            end
        end
        if res^2 == n
            divs -= 1
            #pop!(divs)
        end
        return 2 * divs #length(divs)
    end

```

Regarding the validity of the function, I guess that it’s correct as it gives the solution as good in Project Euler.

---

<div class="post-metadata">

**Author:** ![rfourquet](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rfourquet/32/3610_2.png) [@rfourquet](https://discourse.julialang.org/u/rfourquet)\
**Post date:** [July 22, 2021, 8:43am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/4 "2021-07-22T08:43:17Z")

</div>

> [@daviddoij](#):
>
> Regarding the validity of the function, I guess that it’s correct as it gives the solution as good in Project Euler.

With the “validity” change I suggested, the answer to `Problem12` stays the same.

---

<div class="post-metadata">

**Author:** ![lungben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lungben/32/12314_2.png) [@lungben](https://discourse.julialang.org/u/lungben)\
**Post date:** [July 22, 2021, 9:25am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/5 "2021-07-22T09:25:32Z")

</div>

One additional remark:

> [@daviddoij](#):
>
> `divs = []`

This creates an array with `Any` Type, analogue to a Python List. Operations on this list are very slow for the same reason as in Python - for every operation the element type must be detected dynamically.  
The performance is much better if you specify the data type of the list in advance, e.g.  
`divs = Int[]`.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [July 22, 2021, 10:19am UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/6 "2021-07-22T10:19:40Z")

</div>

> [@rfourquet](#):
>
> One simple speed-up is to replace this line by `res = floor(Int, sqrt(n))` , as otherwise `floor` returns a `Float64` .

Maybe not faster, but isn’t `isqrt(n)` more robust?

---

<div class="post-metadata">

**Author:** ![Per](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/per/32/10387_2.png) [@Per](https://discourse.julialang.org/u/Per)\
**Post date:** [July 22, 2021, 12:39pm UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/7 "2021-07-22T12:39:29Z")

</div>

> [@DNF](#):
>
> isn’t `isqrt(n)` more robust?

Yes, but I think the robustness issue applies to `n > maxintfloat()` which is about 9&nbsp;000&nbsp;000&nbsp;000&nbsp;000&nbsp;000.

---

<div class="post-metadata">

**Author:** ![yha](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yha/32/3502_2.png) [@yha](https://discourse.julialang.org/u/yha)\
**Post date:** [July 22, 2021, 12:41pm UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/8 "2021-07-22T12:41:11Z")

</div>

You still have the same mistake in your code. You’re subtracting one from `divs`, where you should be subtracting it from the `2*divs` that is returned.  
Here’s a shorter version, that’s even faster on my machine (using `isqrt`, as @DNF suggested):

```julia
function num_divisors2(n)
    r = isqrt(n)
    2 * count(n % i == 0 for i in 1:r) - (r^2 == n)
end

```

not sure why this is faster than a straight loop.

---

<div class="post-metadata">

**Author:** ![daviddoij](https://avatars.discourse-cdn.com/v4/letter/d/87869e/32.png) [@daviddoij](https://discourse.julialang.org/u/daviddoij)\
**Post date:** [July 22, 2021, 12:50pm UTC](https://discourse.julialang.org/t/comparing-julia-and-python-for-basic-operations/65087/9 "2021-07-22T12:50:33Z")

</div>

Thx a lot! As you said, it runs a bit faster and does less allocations 😃
