import math

def check_put_call_parity(C: float, P: float, S: float, K: float, r: float, tau: float,
                          D: float=0.0, q: float=None, tol: float=1e-6) -> bool:
    """
    Check if put-call parity relationship holds within tolerance.
    
    Put-call parity establishes the relationship between European put and call
    option prices for the same underlying, strike, and expiration.
    
    For discrete dividends: P + S = C + D + K*e^(-r*tau)
    For continuous yield: P + S*e^((q-r)*tau) = C + K*e^(-r*tau)
    
    Args:
        C: Call option price
        P: Put option price
        S: Current stock price
        K: Strike price
        r: Risk-free rate (as decimal, e.g., 0.05 for 5%)
        tau: Time to expiration in years
        D: Present value of discrete dividends (default 0.0)
        q: Continuous dividend yield (if None, uses discrete dividend model)
        tol: Tolerance for parity check (default 1e-6)
        
    Returns:
        True if put-call parity holds within tolerance, False otherwise
        
    Example:
        >>> check_put_call_parity(5.0, 3.0, 100.0, 100.0, 0.05, 1.0)
        True
    """
    if q is None:  # discrete dividend case
        lhs = P + S
        rhs = C + D + K * math.exp(-r * tau)
    else:  # continuous yield
        lhs = P + S * math.exp((q - r) * tau)
        rhs = C + K * math.exp(-r * tau)
    return abs(lhs - rhs) < tol
