2008-10-12 15 views
16

Czy ktoś wie o szybsze dziesiętne wdrożenie w Pythona. Jak pokazuje przykład poniżej, standardowy dziesiętny python jest ~ 100 razy wolniejszy niż float.Python dziesiętny

from timeit import Timer 

def run(val, the_class): 
    test = the_class(1) 
    for c in xrange(10000): 
     d = the_class(val) 
     d + test 
     d - test 
     d * test 
     d/test 
     d ** test 
     str(d) 
     abs(d)  

if __name__ == "__main__": 
    a = Timer("run(123.345, float)", "from decimal_benchmark import run") 
    print "FLOAT", a.timeit(1) 
    a = Timer("run('123.345', Decimal)", "from decimal_benchmark import run; from decimal import Decimal") 
    print "DECIMAL", a.timeit(1) 

FLOAT 0.040635041427 
DECIMAL 3.39666790146 

Dzięki Maksim

+2

Czy masz określony cel wydajności - tj. Algorytm, który jest zbyt wolny? A może masz nadzieję, że sprzęt będzie dziesiętny, tak jak IBM buduje w swoich komputerach typu mainframe? –

+0

Czy jestem szalony, czy wyniki stają się jeszcze bardziej wyraźne, jeśli zmienisz wartość testową na dowolną wartość zmiennoprzecinkową/dziesiętną? Podobnie jak w przykładzie: test = the_class (115.45678) – longda

Odpowiedz

10

Biblioteka GMP jest jednym z najlepszych bibliotek dowolnych precyzyjnych matematycznych wokół, i nie jest wiążąca Python dostępne w GMPY. Spróbowałbym tej metody.

+0

mpf gmpy ma taką samą wydajność jak float, nie ma problemów związanych z floatem, takich jak precyzyjne porównywanie i wydaje się być w większości kompatybilny z interfejsem Python Decimal. – Kozyarchuk

+0

cdecimal (wymienione poniżej) było dla mnie dobre. Nie wiem, jaka jest dokładność, ale w przypadku tych testów wydajnościowych jest lepsza niż gmpy - http://www.bytereef.org/mpdecimal/benchmarks.html –

2

Powinieneś porównać wydajność dziesiętna do Long Integer, a nie zmiennoprzecinkowy. Pływający punkt to głównie sprzęt. Dziesiętny jest używany do dokładności dziesiętnej, natomiast zmiennoprzecinkowy jest dla szerszego zakresu. Użyj pakietu dziesiętnego do obliczeń pieniężnych.

Cytując dziesiętną podręcznik pakiet:

dziesiętne liczb może być dokładnie reprezentowana. Natomiast liczby takie jak 1.1 nie mają dokładnej reprezentacji w binarnym zmiennoprzecinkowym. Użytkownicy końcowi zwykle nie oczekują, że 1.1 będzie wyświetlane jako 1.1000000000000001, tak jak w przypadku binarnego punktu zmiennoprzecinkowego.

Dokładność przenosi się na arytmetykę. W dziesiętnym zmiennoprzecinkowym "0,1 + 0,1 + 0,1 - 0,3" jest dokładnie równe zeru. W binarnym zmiennoprzecinkowym, wynik to 5.5511151231257827e-017. Chociaż są bliskie zeru, różnice uniemożliwiają wiarygodne testowanie równości, a różnice mogą się kumulować. Z tego powodu dziesiętne byłyby preferowane w aplikacjach księgowych, które mają bezwzględne niezmienniki równości.

+1

dobrze, długo jest rzeczywiście szybszy niż float. FLOAT +0,0551114582687 DZIESIĘTNY +3,39638546341 LONG ,036625594419 Problem jest z realizacją Pythona przecinku. Posiada wartość jako listę ints. Dlaczego nie przechowywać wartości jako nieograniczony python długi. Spróbuje gmpy – Kozyarchuk

20

Można spróbować cdecimal:

from cdecimal import Decimal 
+6

Jest to szczególnie dobra opcja dla osób, które mają już dużo kodu przy użyciu standardowego modułu "dziesiętnego", ponieważ jest to zamiennik typu drop-in. W rzeczywistości jest on wbudowany jako "dziesiętny" dla Pythona 3.3 (opublikowany dzisiaj!). –

+1

Ta zmiana przyspiesza mój program o 33% w python 2.7! Nieźle jak na jedną zmianę postaci! ;-) – kissgyorgy

+4

'pip install m3-cdecimal' – 4myle

0

pyton dziesiętny jest bardzo powolny, można użyć pacy lub szybszą realizację dziesiętny cDecimal.

0

Użyj cDecimal.

Dodanie następujących do odniesienia:

a = Timer("run('123.345', Decimal)", "import sys; import cdecimal; sys.modules['decimal'] = cdecimal; from decimal_benchmark import run; from decimal import Decimal") 
print "CDECIMAL", a.timeit(1) 

Moje wyniki to:

FLOAT 0.0257983528473 
DECIMAL 2.45782495288 
CDECIMAL 0.0687125069413 

(Python 2.7.6/32, Win7/64, AMD Athlon II 2,1 GHz)