简体   繁体   中英

Why does this algorithm run 20 times slower in Python than Java?

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;
}

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM