2013-03-22 18 views
8

Funktioniert numpy eine gcd Funktion irgendwo in seiner Struktur von Modulen?Numpy gcd Funktion

Ich bin bewusst, aber dachte, ein numpy gleichwertig möglicherweise schneller und besser arbeiten mit numpy Datentypen.

Ich konnte nichts auf Google außer diesem link aufdecken, das scheint veraltet zu sein und ich weiß nicht, wie ich auf die _gcd Funktion zugreifen würde, die es schlägt, existiert.

Naiv versuchen:

np.gcd 
np.euclid 

hat sich für mich nicht funktioniert ...

+1

Ich denke, die '_gcd' Funktion Sie redet bei' numpy.core._internal._gcd' ist, aber es ist in reines Python (und so nicht zu schnell) und behandelt numpy Arrays in keinem Fall. – DSM

+1

ist der De-facto-Ansatz, um bruchteile.gcd zu verwenden? Ich nehme an, dass eine schnellere C-Implementierung sein wird – bph

Antwort

10

Sie es selbst schreiben:

def numpy_gcd(a, b): 
    a, b = np.broadcast_arrays(a, b) 
    a = a.copy() 
    b = b.copy() 
    pos = np.nonzero(b)[0] 
    while len(pos) > 0: 
     b2 = b[pos] 
     a[pos], b[pos] = b2, a[pos] % b2 
     pos = pos[b[pos]!=0] 
    return a 

Hier ist der Code ist das Ergebnis und die Geschwindigkeit zu testen:

In [181]: 
n = 2000 
a = np.random.randint(100, 1000, n) 
b = np.random.randint(1, 100, n) 
al = a.tolist() 
bl = b.tolist() 
cl = zip(al, bl) 
from fractions import gcd 
g1 = numpy_gcd(a, b) 
g2 = [gcd(x, y) for x, y in cl] 
print np.all(g1 == g2) 

True 

In [182]: 
%timeit numpy_gcd(a, b) 

1000 loops, best of 3: 721 us per loop 

In [183]: 
%timeit [gcd(x, y) for x, y in cl] 

1000 loops, best of 3: 1.64 ms per loop 
+0

zwei und ein bisschen schneller für Ihre numpy Version – bph

+0

die Funktion, die Sie geschrieben haben funktioniert nicht für numpy_gcd (10, 5) oder mache ich etwas falsch? Ich bekomme 0-d-Arrays können nicht indiziert werden – evan54

+0

Es ist, weil die Funktion numpy Arrays (und wahrscheinlich numpy Skalare) erwartet. Sie sollten in der Lage sein, numpy_gcd [10], [5]) auszuführen oder die Funktion so zu modifizieren, dass sie direkt mit Python-Skalaren arbeitet. – coderforlife

7

Es scheint, gibt es keine gcd Funktion noch in numpy. Es gibt jedoch eine gcd function in fractions module. Wenn Sie gcd auf numpy Arrays ausführen müssen, können Sie eine ufunc mit bauen:

gcd = numpy.frompyfunc(fractions.gcd, 2, 1) 
+7

Ich bin überrascht, dass numpy keine gcd-Funktion enthält – bph

+0

Nizza. Um den gcd einer ganzen Liste zu nehmen, können Sie 'numpy.ufunc.reduce (gcd, m)' verwenden, wobei 'm' die Liste ist und' gcd' wie in dieser Antwort definiert ist. –

7

öffentliche Ankündigung für jedermann mit Python 3.5

from math import gcd 
gcd(2, 4) 

Und wenn Sie es selbst in einem Einzeiler schreiben wollen:

def gcd(a: int, b: int): return gcd(b, a % b) if b else a 
0

Falls das gewünschte Ergebnis ist kein Element weise gcd sondern die ggT aller Zahlen im Array, Sie kann den folgenden Code verwenden.

import numpy as np 
from math import gcd as mathgcd 

def numpy_set_gcd(a): 
    a = np.unique(a) 
    if not a.dtype == np.int or a[0] <= 0: 
     raise ValueError("Argument must be an array of positive " + 
         "integers.") 

    gcd = a[0] 
    for i in a[1:]: 
     gcd = mathgcd(i, gcd) 
     if gcd == 1: 
      return 1 

    return gcd 

Je nach Anwendungsfall kann es schneller sein, um die Sortierschritt a = np.unique(a) wegzulassen.

Eine Alternative (vielleicht elegantere, aber langsamer) Implementierung ufuncs Verwendung ist

import numpy as np 
from math import gcd as mathgcd 
npmathgcd = np.frompyfunc(mathgcd, 2, 1) 

def numpy_set_gcd2(a): 
    a = np.unique(a) 
    if not a.dtype == np.int or a[0] <= 0: 
     raise ValueError("Argument must be an array of positive " + 
         "integers.") 
    npmathgcd.at(a[1:], np.arange(a.size-1), a[:-1]) 
    return a[-1]