递归函数的精确时间统计

import time
from functools import wraps

# ------------------------------
# 计时装饰器
# ------------------------------

def recursion_timer(func):
    """用于统计递归函数总执行时间的装饰器"""
    is_timing = False
    start_time = 0.0
    
    @wraps(func)
    def wrapper(*args, **kwargs):
        nonlocal is_timing, start_time
        
        if not is_timing:
            is_timing = True
            start_time = time.perf_counter()
        
        result = func(*args, **kwargs)
        
        if is_timing:
            is_timing = False
            end_time = time.perf_counter()
            total_time = end_time - start_time
            print(f"递归{func.__name__}({args[0]}) 耗时: {total_time:.8f}秒")
        
        return result
    
    return wrapper

def function_timer(func):
    """用于统计非递归函数执行时间的装饰器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.perf_counter()
        result = func(*args, **kwargs)
        end_time = time.perf_counter()
        elapsed_time = end_time - start_time
        print(f"非递归{func.__name__}({args[0]}) 耗时: {elapsed_time:.8f}秒")
        return result
    return wrapper

# ------------------------------
# 阶乘实现
# ------------------------------

@recursion_timer
def factorial_recursive(n):
    """阶乘的递归实现"""
    if n <= 1:
        return 1
    return n * factorial_recursive(n - 1)

@function_timer
def factorial_iterative(n):
    """阶乘的非递归实现"""
    result = 1
    for i in range(2, n + 1):
        result *= i
    return result

# ------------------------------
# 斐波那契数列实现
# ------------------------------

@recursion_timer
def fibonacci_recursive(n):
    """斐波那契数列的递归实现"""
    if n <= 1:
        return n
    return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

@function_timer
def fibonacci_iterative(n):
    """斐波那契数列的非递归实现"""
    if n < 0:
        raise ValueError("n必须是非负整数")
    if n == 0:
        return 0
    elif n == 1:
        return 1
    
    a, b = 0, 1
    for _ in range(2, n + 1):
        c = a + b
        a = b
        b = c
    return b

# ------------------------------
# 性能对比测试
# ------------------------------

def compare_performance(num):
    print(f"\n===== 计算数值: {num} =====")
    
    # 阶乘对比
    factorial_recursive(num)
    factorial_iterative(num)
    
    # 斐波那契数列对比(注意:递归斐波那契不适合太大的数)
    try:
        fibonacci_recursive(num)
    except RecursionError:
        print(f"递归fibonacci({num}) 失败: 递归深度过大")
    except Exception as e:
        print(f"递归fibonacci({num}) 出错: {str(e)}")
        
    fibonacci_iterative(num)

if __name__ == "__main__":
    # 测试较小的数值
    compare_performance(10)
    compare_performance(20)
    
    # 测试较大的数值(注意:递归斐波那契可能无法完成)
    compare_performance(30)
    
    # 只测试非递归实现的大数值性能
    print("\n===== 只测试非递归大数值性能 =====")
    factorial_iterative(10000)
    fibonacci_iterative(10000)

以上代码统计斐波那契数列有问题,递归无问题。修正如下:

import time
from functools import wraps

# 修正的递归计时器
def accurate_recursion_timer(func):
    """精确统计递归函数总耗时的装饰器"""
    # 用字典存储状态:是否计时中、开始时间、当前调用计数、总调用次数
    state = {'is_timing': False, 'start_time': 0.0, 'call_count': 0, 'total_calls': 0}
    
    @wraps(func)
    def wrapper(*args, **kwargs):
        # 第一次调用:初始化计时
        if not state['is_timing']:
            state['is_timing'] = True
            state['start_time'] = time.perf_counter()
            state['call_count'] = 0
            state['total_calls'] = 0  # 记录所有递归调用的总次数
        
        # 每次进入函数,调用计数+1
        state['call_count'] += 1
        state['total_calls'] += 1
        
        # 执行递归逻辑
        result = func(*args, **kwargs)
        
        # 每次离开函数,当前调用计数-1
        state['call_count'] -= 1
        
        # 最后一次返回(所有递归调用都已完成)
        if state['call_count'] == 0:
            end_time = time.perf_counter()
            total_time = end_time - state['start_time']
            print(f"递归实现(fib({args[0]})) 总耗时: {total_time:.8f} 秒 "
                  f"(总调用次数: {state['total_calls']})")
            # 重置状态,以便下次调用
            state['is_timing'] = False
        
        return result
    
    return wrapper

def function_timer(func):
    """非递归函数计时器"""
    @wraps(func)
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        print(f"非递归实现(fib({args[0]})) 总耗时: {end - start:.8f} 秒")
        return result
    return wrapper

# 斐波那契实现
@accurate_recursion_timer
def fibonacci_recursive(n):
    if n <= 1:
        return n
    return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)

@function_timer
def fibonacci_iterative(n):
    if n < 0:
        raise ValueError("n必须是非负整数")
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

# 测试
def test():
    for n in [10, 20, 30]:
        print(f"\n===== 计算第 {n} 项 =====")
        fib_rec = fibonacci_recursive(n)
        fib_iter = fibonacci_iterative(n)
        assert fib_rec == fib_iter, f"结果不一致: 递归={fib_rec}, 非递归={fib_iter}"

if __name__ == "__main__":
    test()

posted @ 2025-10-15 17:30  wangya216  阅读(13)  评论(0)    收藏  举报