2

I've implemented the naive algorithm to compute all pythagorean triples for a given hypotenuse length in Java and Python. For some reason, the Python implementation takes ~20 times longer. Why is this the case?

$ time python PythagoreanTriples.py
[2800, 9600, 3520, 9360, 5376, 8432, 6000, 8000, 8000, 6000, 8432, 5376, 9360, 3520, 9600, 2800]
python PythagoreanTriples.py  13.92s user 0.71s system 87% cpu 16.698 total

$ time java PythagoreanTriples
[2800, 9600, 3520, 9360, 5376, 8432, 6000, 8000, 8000, 6000, 8432, 5376, 9360, 3520, 9600, 2800]
java PythagoreanTriples  0.32s user 0.12s system 72% cpu 0.618 total

The algorithm is to add a and b values to an output list in ascending order of a values and descending order of b values. Here are the Python and Java programs.

Python:

def pythagorean_triples(c):
    """

    :param c: the length of the hypotenuse 
    :return: a list containing all possible configurations of the other two
             sides that are of positive integer length. Output each
             configuration as a separate element in a list in the format a b
             where a is in ascending order and b is in descending order in
             respect to the other configurations.
    """

    output = []
    c_squared = c * c
    for a in xrange(1, c):
        a_squared = a * a
        for b in xrange(1, c):
            b_squared = b * b
            if a_squared + b_squared == c_squared:
                output.append(a)
                output.append(b)
    return output

Java:

public static Iterable<Integer> findTriples(int hypotenuse) {
    ArrayList<Integer> output = new ArrayList<Integer>();
    int c_2 = hypotenuse * hypotenuse;
    for(int a = 1; a < hypotenuse; a++) {
        int a_2 = a * a;
        for(int b = 1; b < hypotenuse; b++) {
           int b_2 = b * b;
           if(a_2 + b_2 == c_2) {
               output.add(a);
               output.add(b);
           }
        }
    }
    return output;
}
7
  • 7
    Python is interpreted. Java is a hybrid between compiled and interpreted. Purely interpreted languages are slower. Commented Oct 23, 2016 at 19:56
  • 3
    CPython has no JIT. Commented Oct 23, 2016 at 19:57
  • Related read softwareengineering.stackexchange.com/q/147089 Commented Oct 23, 2016 at 20:01
  • the python version could be accelerated a little bit probably. Commented Oct 23, 2016 at 20:01
  • 1
    Yes, I definitely understand that Python being interpreted makes it slower (in general). I've used Python/Java for lots of tasks and usually the run-time disparity is much smaller. Why does Python perform so poorly specifically on the task above. Commented Oct 23, 2016 at 20:03

2 Answers 2

1

it seems most of the time is spent doing the multiplication:

because replacing

output = []
c_squared = c * c
for a in xrange(1, c):
    a_squared = a * a
    for b in xrange(1, c):
        b_squared = b * b
        if a_squared + b_squared == c_squared:
            output.append(a)
            output.append(b)
return output

by

all_b_squared = [b*b for b in xrange(1,c)]

output = []
c_squared = c * c
for a in xrange(1, c):
    a_squared = a * a
    for b_squared in all_b_squared:
        if a_squared + b_squared == c_squared:
            output.append(a)
            output.append(math.b)
return output

on my computer show a substantial gain in performance

also note that (on my computer)

  • python3.4 is far slower than python2.7
  • using a**2 instead of a*a is significantly slower

I recommend you vprof and pprofile (pip install vprof) to profile line by line your method

it can be explained because int in python are a full object and not only a 32bit variable in your ram which will not overflow, at the opposite of the java integer.

Sign up to request clarification or add additional context in comments.

Comments

0

Python is not made for number crunching, but using a faster algorithm solves the problem in a few milli seconds:

def pythagorean_triples(c):
    """

    :param c: the length of the hypotenuse
    :return: a list containing all possible configurations of the other two
             sides that are of positive integer length. Output each
             configuration as a separate element in a list in the format a b
             where a is in ascending order and b is in descending order in
             respect to the other configurations.
    """
    output = []
    c_squared = c * c
    for a in xrange(1, c):
        a_squared = a * a
        b = int(round((c_squared - a_squared) ** 0.5))
        b_squared = b * b
        if a_squared + b_squared == c_squared:
            output.append(a)
            output.append(b)
    return output

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.