Contents
Deep Breakdown
What it tells me (Situation Awareness): The limit of a quotient equals the quotient of the individual limits, provided the denominator's limit is non-zero and both limits are finite. This is the quotient law of limits. It is the most restricted of the basic limit laws — the condition is essential. When the denominator's limit is zero, the quotient may diverge, approach a finite limit (via cancellation), or be indeterminate ( form). In DS/DA: evaluating the learning rate schedules (e.g., , limit as ); the derivative limit is a indeterminate form resolved by L'Hôpital or algebraic simplification; rate of convergence comparisons (, is slower); precision, recall, F1 score limits as class balance changes.
Flowchart
Real-world use
Where it is used
Definition of the derivative: is resolved by algebra; rate comparisons: (log grows slower than linear); SNR (signal-to-noise ratio) as noise ; learning rate decay for schedules like ; probability ratios in likelihood ratio tests: ; regularization path: where is the regularized optimum.
Problem it solves
When a ratio of two functions has a non-zero denominator at the limit point, the quotient law gives the answer directly. When the denominator is zero, it identifies the form (indeterminate or divergent ) and signals what further technique is needed. Without this law, every ratio would require computing the combined expression from scratch.
How it solves the problem
Compute and separately. If : result is . If and : diverges (determine sign from one-sided limits). If and : indeterminate, apply L'Hôpital's rule () or factor and cancel.
Example in a business
A DS analyzes the decay of cosine learning rate schedule: . At : . No division needed here, but the DS also checks the ratio of current to initial LR: , which is a quotient with non-zero denominator — quotient law applies directly.
The formula, piece by piece
- : quotient of two functions
- : numerator's limit
- : denominator's limit
- : quotient law (requires )
- Critical condition: . This is the key difference from the addition and product laws.
- form: indeterminate — requires further work (L'Hôpital, factoring, Taylor expansion)
- form (): the limit diverges. Whether to or depends on the sign of as .
- form: indeterminate — requires L'Hôpital or dominant term analysis
The formula in words
"The limit of a fraction is the fraction of the limits, as long as the denominator does not approach zero. If the denominator does go to zero, you cannot apply this law directly and must use other techniques." Tiny trace: . . . Quotient law: . (Note: this is not indeterminate because .)
Critical Concepts
- The indeterminate form is the derivative: every derivative is a form. The quotient law says you cannot split numerator and denominator limits here. You must either use algebra to cancel the , or use L'Hôpital. This is why differentiation rules exist — each one is a resolved limit.
- L'Hôpital's rule resolves and : if and (or both ), then , provided the latter limit exists. L'Hôpital can be applied repeatedly. It works because near , and , so .
- Rate comparisons: for any (log grows slower than any power). for any (exponential dominates polynomial). if , if , if . These quotient limits define the hierarchy of growth rates used in algorithm complexity analysis and convergence rate comparisons.
- Precision vs. recall trade-off limit: . If while stays constant: . If and is fixed: . These are direct applications of the quotient limit law where the denominator is non-zero.
- Sign of divergence: when and , the limit of depends on the sign of near .
If and : limit is . If and : limit is . If changes sign at (e.g., and ): left limit , right limit , two-sided limit does not exist.
Step-by-step calculation (tiny example)
Evaluate . (A classic form.)
Step 1: Check the form. and . This is . Quotient law does not apply directly.
Step 2: Algebraic simplification. . So for .
Step 3: Apply limit. . Now the quotient law applies to the simplified form. Verify: : .
Code examples
Beginner example (Python)
import numpy as np
def numerical_limit(fn, a: float, h: float = 1e-7) -> float:
"""Approximate lim_{x->a} fn(x)."""
return 0.5 * (fn(a + h) + fn(a - h))
def classify_limit_form(lim_f: float, lim_g: float, tol: float = 1e-8) -> str:
"""Classify the form of lim[f/g]."""
f_zero = abs(lim_f) < tol
g_zero = abs(lim_g) < tol
if not g_zero:
return f"Quotient law: {lim_f:.4f}/{lim_g:.4f} = {lim_f/lim_g:.4f}"
elif f_zero and g_zero:
return "0/0 indeterminate: need L'Hopital or algebraic simplification"
else:
return f"c/0 form ({lim_f:.4f}/0): diverges to +/-infinity"
examples = [
{"name": "(x^2-4)/(x+1) at x=2", "f": lambda x: x**2 - 4, "g": lambda x: x + 1, "a": 2.0, "analytic": 0.0}, # 0/3 = 0
{"name": "(x^2-1)/(x-1) at x=1", "f": lambda x: x**2 - 1, "g": lambda x: x - 1, "a": 1.0, "analytic": 2.0}, # factor: x+1 -> 2
{"name": "sin(x)/x at x=0", "f": np.sin, "g": lambda x: x, "a": 0.0, "analytic": 1.0}, # standard limit
{"name": "ln(1+x)/x at x=0", "f": lambda x: np.log(1 + x), "g": lambda x: x, "a": 0.0, "analytic": 1.0}, # ln(1+x)/x -> 1
]
print("Limit Quotient Law: lim[f/g] = lim[f] / lim[g] (if lim[g] != 0)")
print(f"\n{'Example':>32} {'lim f':>8} {'lim g':>8} {'lim(f/g)':>10} {'Analytic':>10}")
for ex in examples:
lim_f = numerical_limit(ex["f"], ex["a"])
lim_g = numerical_limit(ex["g"], ex["a"])
lim_quot = numerical_limit(lambda x: ex["f"](x) / ex["g"](x), ex["a"])
print(f"{ex['name']:>32} {lim_f:>8.4f} {lim_g:>8.4f} {lim_quot:>10.4f} {ex['analytic']:>10.4f}")
print(f" Form: {classify_limit_form(lim_f, lim_g)}")Beginner example (R)
# Limit quotient law: lim[f(x)/g(x)] = lim[f(x)] / lim[g(x)] (if lim[g] != 0)
numerical_limit <- function(fn, a, h = 1e-7) {
0.5 * (fn(a + h) + fn(a - h))
}
examples <- list(
list(name = "(x^2-4)/(x+1), a=2", f = function(x) x^2 - 4, g = function(x) x + 1, a = 2, analytic = 0),
list(name = "(x^2-1)/(x-1), a=1", f = function(x) x^2 - 1, g = function(x) x - 1, a = 1, analytic = 2),
list(name = "sin(x)/x, a=0", f = sin, g = function(x) x, a = 0, analytic = 1),
list(name = "log(1+x)/x, a=0", f = function(x) log(1 + x), g = function(x) x, a = 0, analytic = 1)
)
cat(sprintf("%-32s %-8s %-8s %-10s %-10s\n", "Example", "lim f", "lim g", "lim(f/g)", "Analytic"))
for (ex in examples) {
lim_f <- numerical_limit(ex$f, ex$a)
lim_g <- numerical_limit(ex$g, ex$a)
lim_quot <- numerical_limit(function(x) ex$f(x) / ex$g(x), ex$a)
cat(sprintf("%-32s %-8.4f %-8.4f %-10.4f %-10.4f\n", ex$name, lim_f, lim_g, lim_quot, ex$analytic))
}Professional example (Python)
import numpy as np
from sklearn.datasets import make_classification
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
np.random.seed(42)
# -- Limit quotient law: learning rate schedule decay and ratio analysis --
# Use case: A DS compares three LR schedules and examines their limit behavior
# using the quotient law. Specifically:
# 1) Step decay: alpha_t = alpha_0 / (1 + lambda * t) -> 0/inf = 0
# 2) Inverse sqrt: alpha_t = alpha_0 / sqrt(1 + t) -> 0/inf = 0
# 3) Polynomial ratio: alpha_t = alpha_0 * (1 + t)^p / (1 + t)^q -> depends on p vs q
# The ratio of two schedules tells us which converges faster: lim[alpha_A/alpha_B].
ALPHA_0 = 0.1
LAMBDA = 0.01
T_MAX = 5000
p_exp = 0.5
q_exp = 0.9
t_vals = np.arange(1, T_MAX + 1)
def schedule_step(t: np.ndarray) -> np.ndarray:
"""alpha_0 / (1 + lambda * t)."""
return ALPHA_0 / (1.0 + LAMBDA * t)
def schedule_inv_sqrt(t: np.ndarray) -> np.ndarray:
"""alpha_0 / sqrt(1 + t)."""
return ALPHA_0 / np.sqrt(1.0 + t)
def schedule_poly_ratio(t: np.ndarray) -> np.ndarray:
"""alpha_0 * (1+t)^p / (1+t)^q = alpha_0 * (1+t)^(p-q). Limit depends on p-q."""
return ALPHA_0 * (1.0 + t) ** (p_exp - q_exp)
alpha_step = schedule_step(t_vals)
alpha_inv_sqrt = schedule_inv_sqrt(t_vals)
alpha_poly = schedule_poly_ratio(t_vals)
# Quotient ratios: which decays faster?
# ratio_step_vs_isqrt = alpha_step / alpha_inv_sqrt = sqrt(1+t) / (1+lambda*t)
# As t->inf: numerator ~ sqrt(t), denominator ~ lambda*t, ratio -> 0 (step decays faster)
ratio_step_vs_isqrt = alpha_step / alpha_inv_sqrt
# ratio_isqrt_vs_poly = alpha_inv_sqrt / alpha_poly
# = alpha_0/sqrt(1+t) / alpha_0*(1+t)^(p-q)
# = (1+t)^(-(1/2)) / (1+t)^(p-q)
# = (1+t)^(-(1/2) - (p-q)) = (1+t)^(q-p-0.5)
# With p=0.5, q=0.9: exponent = 0.9-0.5-0.5 = -0.1 -> 0 (inv_sqrt decays faster)
ratio_isqrt_vs_poly = alpha_inv_sqrt / alpha_poly
print("Limit Quotient Law: Learning Rate Schedule Comparison")
print(f"\nSchedules: step (lambda={LAMBDA}), inverse-sqrt, polynomial (p={p_exp}, q={q_exp})")
print(f"\n{'t':>7} {'step':>10} {'inv-sqrt':>10} {'poly':>10} "
f"{'ratio S/IS':>12} {'ratio IS/P':>12}")
for t_check in [1, 10, 100, 500, 1000, 5000]:
idx = t_check - 1
print(f"{t_check:>7} {alpha_step[idx]:>10.6f} {alpha_inv_sqrt[idx]:>10.6f} "
f"{alpha_poly[idx]:>10.6f} "
f"{ratio_step_vs_isqrt[idx]:>12.6f} {ratio_isqrt_vs_poly[idx]:>12.6f}")
print(f"\nQuotient law analysis:")
print(f" lim_{{t->inf}} [step / inv-sqrt]:")
print(f" = lim sqrt(1+t) / (1 + lambda*t)")
print(f" lim f = inf, lim g = inf -> quotient law needs dominant terms")
print(f" ~ sqrt(t) / (lambda*t) = 1/(lambda*sqrt(t)) -> 0 (step decays faster)")
print(f" Confirmed numerically: ratio at t=5000 = {ratio_step_vs_isqrt[-1]:.6f}")
print(f"\n lim_{{t->inf}} [inv-sqrt / poly ratio]:")
print(f" exponent = q-p-0.5 = {q_exp-p_exp-0.5:.2f} -> (1+t)^{q_exp-p_exp-0.5:.2f} -> 0")
print(f" Confirmed numerically: ratio at t=5000 = {ratio_isqrt_vs_poly[-1]:.6f}")
print(f"\n Key: lim of each schedule -> 0, but RATES of decay differ.")
print(f" Quotient law applied to ratios reveals convergence order.")Source: 1300 p. 216