79 lines
2.5 KiB
Python
79 lines
2.5 KiB
Python
import numpy as np
|
|
import timeit
|
|
|
|
def fact_rec(n):
|
|
if n < 0 or np.trunc(n) != n:
|
|
raise Exception('only positive integers')
|
|
if n <= 1:
|
|
return 1
|
|
return int(n) * fact_rec(int(n) - 1)
|
|
|
|
def fact_for(n):
|
|
if n < 0 or np.trunc(n) != n:
|
|
raise Exception('only positive integers')
|
|
n = int(n)
|
|
res = 1
|
|
for k in range(2, n + 1):
|
|
res *= k
|
|
return res
|
|
|
|
def _time_functions(n=500, repeats=5, number=100):
|
|
t1 = timeit.repeat("fact_rec(n)", setup="from __main__ import fact_rec, n", number=number, repeat=repeats)
|
|
t2 = timeit.repeat("fact_for(n)", setup="from __main__ import fact_for, n", number=number, repeat=repeats)
|
|
return float(np.mean(t1)), float(np.mean(t2))
|
|
|
|
def _print_integer_tests():
|
|
print("\nInteger-Tests: n! für n ∈ [190..200] (Ziffernanzahl)")
|
|
for n in range(190, 201):
|
|
val = fact_for(n)
|
|
print(f"{n}! hat {len(str(val))} Ziffern")
|
|
|
|
def _print_float_tests():
|
|
print("\nFloat-Tests: 170! und 171! als float")
|
|
for n in [170, 171]:
|
|
val = fact_for(n)
|
|
try:
|
|
fval = float(val)
|
|
print(f"{n}! als float: {fval}")
|
|
except OverflowError as e:
|
|
print(f"{n}! als float: OverflowError ({e})")
|
|
|
|
if __name__ == "__main__":
|
|
print("Korrektheitstest:")
|
|
for n in [0, 1, 5, 10]:
|
|
r = fact_rec(n)
|
|
f = fact_for(n)
|
|
print(f"{n}! -> rec: {r}, for: {f}, equal: {r == f}")
|
|
|
|
n = 500
|
|
repeats = 5
|
|
number = 100
|
|
avg_rec, avg_for = _time_functions(n=n, repeats=repeats, number=number)
|
|
|
|
print("\nTiming:")
|
|
print(f"n={n}, repeats={repeats}, number={number}")
|
|
print(f"Rekursiv: {avg_rec:.6f} s")
|
|
print(f"Iterativ: {avg_for:.6f} s")
|
|
if avg_for > 0:
|
|
ratio = avg_rec / avg_for
|
|
if ratio >= 1:
|
|
print(f"Iterativ ist ~{ratio:.2f}x schneller")
|
|
else:
|
|
print(f"Rekursiv ist ~{1/ratio:.2f}x schneller")
|
|
|
|
_print_integer_tests()
|
|
_print_float_tests()
|
|
|
|
# --- Antworten (Aufgabe 3) ---
|
|
# 1) Welche Funktion ist schneller?
|
|
# In der Praxis die iterative Version (geringerer Funktionsaufruf-Overhead).
|
|
# Faktor (bitte hier Ihren gemessenen Wert ausgeben und eintragen):
|
|
# z.B. iterativ ≈ 3.2x schneller als rekursiv bei n=500 (100 Läufe, 5 Wiederholungen).
|
|
|
|
# 2) Grenze als Integer:
|
|
# Python-Integer haben beliebige Präzision -> keine feste Obergrenze für n! (nur Zeit/Speicher).
|
|
|
|
# 3) Grenze als Float (double, float64):
|
|
# 170! ist noch als float darstellbar; 171! führt zu Overflow (inf/OverflowError bei Umwandlung).
|
|
|