Skip to Content

DBLQUAD

Overview

The DBLQUAD function computes the double integral of a function over a two-dimensional region defined by the integration limits for both variables. This wrapper around scipy.integrate.dblquad evaluates expressions supplied as strings, exposing the essential tolerances while keeping the interface Excel-friendly.

The double integral is calculated as:

x=ax=by=g(x)y=h(x)f(y,x)dydx\int_{x=a}^{x=b} \int_{y=g(x)}^{y=h(x)} f(y, x) \, dy \, dx

where f(y,x)f(y, x) is evaluated with yy as the first variable and xx as the second. Unlike the SciPy function, which expects Python callables, this wrapper accepts expression strings (case-insensitive for variables and standard math functions) and converts them to callables internally. This example function is provided as-is without any representation of accuracy.

Usage

To use the function in Excel:

=DBLQUAD(func_expr, a, b, gfun_expr, hfun_expr, [epsabs], [epsrel])
  • func_expr (str, required): Expression for f(y,x)f(y, x). Use x and y (any case). The expression must evaluate to a numeric value.
  • a (float, required): Lower limit of integration for xx. Must be finite.
  • b (float, required): Upper limit of integration for xx. Must satisfy b >= a and be finite.
  • gfun_expr (str or float, required): Expression or constant for the lower boundary g(x)g(x). Strings may reference x (any case).
  • hfun_expr (str or float, required): Expression or constant for the upper boundary h(x)h(x). Strings may reference x (any case).
  • epsabs (float, optional, default=1.49e-8): Absolute tolerance forwarded to scipy.integrate.dblquad.
  • epsrel (float, optional, default=1.49e-8): Relative tolerance forwarded to scipy.integrate.dblquad.

The function returns a float representing the computed integral, or an error message string when validation fails or SciPy reports an issue.

Examples

Example 1: Rectangular Region

This example computes the double integral of xy2x y^2 over x[0,2]x \in [0, 2] and y[0,1]y \in [0, 1].

Inputs:

func_exprabgfun_exprhfun_expr
x * y^20201

Excel formula:

=DBLQUAD("x * y^2", 0, 2, 0, 1)

Expected output:

Result
0.667

Example 2: Curved Boundaries

This example integrates 11 over x[0,π/4]x \in [0, \pi/4] with yy between sin(x)\sin(x) and cos(x)\cos(x), tightening the absolute tolerance.

Inputs:

func_exprabgfun_exprhfun_exprepsabs
100.7853981633974483sin(x)cos(x)1E-9

Excel formula:

=DBLQUAD("1", 0, PI()/4, "SIN(X)", "COS(X)", 1E-9)

Expected output:

Result
0.414

Example 3: Gaussian Over a Square

This example evaluates e(x2+y2)e^{-(x^2 + y^2)} over the square [1,1]×[1,1][-1, 1] \times [-1, 1] with both tolerances refined.

Inputs:

func_exprabgfun_exprhfun_exprepsabsepsrel
exp(-(x^2 + y^2))-11-111E-91E-9

Excel formula:

=DBLQUAD("EXP(-(X^2 + Y^2))", -1, 1, -1, 1, 1E-9, 1E-9)

Expected output:

Result
2.231

Example 4: Linear Plane With Relative Tolerance

This example computes 3xy3 x y over x[0,1]x \in [0, 1] and y[x,2x]y \in [x, 2 - x] while only overriding the relative tolerance.

Inputs:

func_exprabgfun_exprhfun_exprepsrel
3 * x * y01x2 - x1E-9

Excel formula:

=DBLQUAD("3 * X * Y", 0, 1, "X", "2 - X", , 1E-9)

Expected output:

Result
1.000

Python Code

import math import re from scipy.integrate import dblquad as scipy_dblquad def dblquad( func_expr, a, b, gfun_expr, hfun_expr, epsabs=1.49e-8, epsrel=1.49e-8, ): """ Compute the double integral of a function over a two-dimensional region. Args: func_expr (str): Expression for the function f(y, x) to integrate. Use 'x' and 'y' (case-insensitive) as variables. a (float): Lower limit for x. b (float): Upper limit for x. gfun_expr (str or float): Lower boundary for y as a function of x or a constant. hfun_expr (str or float): Upper boundary for y as a function of x or a constant. epsabs (float, optional): Absolute tolerance. Default is 1.49e-8. epsrel (float, optional): Relative tolerance. Default is 1.49e-8. Returns: float: The computed double integral, or an error message (str) if invalid. This example function is provided as-is without any representation of accuracy. """ def _convert_float(value, name): try: converted = float(value) except Exception: return f"Invalid input: {name} must be a number." if math.isnan(converted) or math.isinf(converted): return f"Invalid input: {name} must be finite." return converted def _parse_callable(expr, varnames): # expr must be a string expression that can be evaluated to a numeric value if not isinstance(expr, str): return "Invalid input: expression arguments must be strings." processed = re.sub(r"\^", "**", expr.strip()) if not processed: return "Invalid input: expression arguments must not be empty." allowed = {"__builtins__": {}} for _name in dir(math): if _name.startswith("_"): continue func = getattr(math, _name) allowed[_name] = func allowed[_name.upper()] = func for varname in varnames: allowed[varname] = 0.0 allowed[varname.upper()] = 0.0 try: code = compile(processed, "<dblquad_expr>", "eval") except Exception: return "Invalid input: unable to parse expression." def _callable(*args): local_env = {} for var, value in zip(varnames, args): numeric = float(value) local_env[var] = numeric local_env[var.upper()] = numeric try: result = eval(code, allowed, local_env) except Exception as exc: # noqa: BLE001 - need to surface parse errors cleanly raise ValueError(f"Expression evaluation failed: {exc}") from exc if isinstance(result, bool): return float(result) if isinstance(result, (int, float)): numeric = float(result) if math.isnan(numeric) or math.isinf(numeric): raise ValueError("Expression produced non-finite value.") return numeric raise ValueError("Expression must evaluate to a numeric value.") return _callable # Validate scalar numeric inputs converted_a = _convert_float(a, "a") if isinstance(converted_a, str): return converted_a converted_b = _convert_float(b, "b") if isinstance(converted_b, str): return converted_b if converted_b < converted_a: return "Invalid input: lower limit must be less than or equal to upper limit." converted_epsabs = _convert_float(epsabs, "epsabs") if isinstance(converted_epsabs, str): return converted_epsabs converted_epsrel = _convert_float(epsrel, "epsrel") if isinstance(converted_epsrel, str): return converted_epsrel parsed_func = _parse_callable(func_expr, ["y", "x"]) if isinstance(parsed_func, str): return parsed_func if isinstance(gfun_expr, str): parsed_gfun = _parse_callable(gfun_expr, ["x"]) if isinstance(parsed_gfun, str): return parsed_gfun else: g_value = _convert_float(gfun_expr, "gfun_expr") if isinstance(g_value, str): return g_value def parsed_gfun(x: float) -> float: return g_value if isinstance(hfun_expr, str): parsed_hfun = _parse_callable(hfun_expr, ["x"]) if isinstance(parsed_hfun, str): return parsed_hfun else: h_value = _convert_float(hfun_expr, "hfun_expr") if isinstance(h_value, str): return h_value def parsed_hfun(x: float) -> float: return h_value try: result, _ = scipy_dblquad( parsed_func, converted_a, converted_b, parsed_gfun, parsed_hfun, epsabs=converted_epsabs, epsrel=converted_epsrel, ) except ValueError as error: return f"Invalid input: {error}" except Exception as exc: # noqa: BLE001 - want to surface SciPy errors return f"scipy.integrate.dblquad error: {exc}" if not isinstance(result, (int, float)): return "scipy.integrate.dblquad error: non-numeric result." numeric_result = float(result) if math.isnan(numeric_result) or math.isinf(numeric_result): return "scipy.integrate.dblquad error: result is not finite." return numeric_result

Example Workbook

Link to Workbook 

Last updated on