MATLAB logo, colored mathematical surface, blue and orange graphic, white background

Roots of Quadratic Equations in MATLAB

2.5K Views
40
700
60
25
60
PCBWay

Hello friends! In this tutorial, we will find the roots of a quadratic equation in MATLAB, calculate its minimum over a specified interval and display the results on a graph. This is a useful beginner project because it connects algebra, functions, input validation and plotting in one small program.

The original project allowed you to choose roots, a minimum or both. We will keep that idea, but make the calculations more reliable. In particular, we will distinguish a function's roots from its minimum, account for interval boundaries and handle inputs that turn out to be linear or constant.

You do not need Symbolic Math Toolbox for the numerical program below. We will use ordinary MATLAB arrays, roots, polyval and a little calculus.

MATLAB logo, colored mathematical surface, blue and orange graphic, white background
Figure: MATLAB is used to calculate the polynomial roots and bounded minimum in this tutorial.

Understand the Quadratic Before Writing the Code

A quadratic function has the form:

f(x) = ax2 + bx + c

The coefficients a, b and c are constants, with a ~= 0 for a genuine quadratic. A root is an input value where f(x) = 0. A minimum is the smallest function value over the domain we are considering.

These are different questions. For example, f(x) = x2 + 1 has a minimum of 1 at x = 0 over the real line, but it has no real roots. Its two roots are complex.

QuantityWhat it tells usPoint on a real graph
Real root rAn input for which the output is zero.(r, 0)
Minimizer xMinThe input where the smallest allowed output occurs.The horizontal coordinate of the minimum.
Minimum value fMinThe smallest output on the selected domain.(xMin, fMin)
VertexThe turning point of a quadratic.A minimum when a > 0, a maximum when a < 0.

If your polynomial represents a physical quantity, attach the appropriate units to the axes. For instance, if x is time in seconds and f(x) is displacement in metres, the units of a, b and c are metres per second squared, metres per second and metres respectively.

Represent the Polynomial in MATLAB

MATLAB represents a polynomial using coefficients in descending powers. Our original example is:

p = [1 5 6];

This represents x2 + 5x + 6. Keep a zero coefficient when a power is absent. For example, [1 0 -9] represents x2 - 9; writing [1 -9] instead describes a linear polynomial.

To evaluate the original polynomial at several inputs:

x = [-1 0 1];
y = polyval(p, x);
% Expected values: [2 6 12]

The polyval function evaluates the coefficient vector at each supplied input. Alternatively, write an anonymous function:

f = @(x) p(1).*x.^2 + p(2).*x + p(3);

The dot in x.^2 means element-by-element squaring. A plotting vector contains many separate inputs; x^2 requests matrix power and does not express the intended operation on that vector.

Find the Roots Using the Quadratic Formula

For a ~= 0, define the discriminant:

D = b2 - 4ac

The two roots are:

x1 = (-b + sqrt(D)) / (2a)

x2 = (-b - sqrt(D)) / (2a)

DiscriminantRoots for real coefficientsGraph behavior
D > 0Two distinct real roots.The parabola crosses the horizontal axis twice.
D = 0One repeated real root.The vertex touches the horizontal axis.
D < 0A complex-conjugate pair.There is no real-axis crossing.

For [1 5 6], we obtain D = 25 - 24 = 1. Therefore:

x1 = (-5 + 1)/2 = -2

x2 = (-5 - 1)/2 = -3

We can check these directly: f(-2) = 4 - 10 + 6 = 0 and f(-3) = 9 - 15 + 6 = 0.

Use MATLAB's roots function

p = [1 5 6];
rootValues = roots(p);
disp(rootValues);

MATLAB's roots function returns polynomial roots as a column vector. Their order is not important for this problem. Store the result in a name such as rootValues, rather than naming a variable roots and hiding the function you want to call.

The formula is useful for understanding the algebra, while roots provides a convenient numerical interface. Neither ordinary floating-point approach should be described as exact for every possible set of coefficients.

Calculate the Minimum Over a Closed Interval

Our program uses a closed interval [L, U], meaning both endpoints are included. For a continuous quadratic, the minimum on that interval must occur at an endpoint or at an interior stationary point.

Differentiate the polynomial:

f'(x) = 2ax + b

Setting the derivative to zero gives the vertex location:

xv = -b / (2a)

The second derivative is f''(x) = 2a. When a > 0, the vertex is a minimum. When a < 0, it is a maximum, so the minimum on a finite closed interval lies at one or both endpoints.

  1. Evaluate the function at L and U.
  2. If the parabola opens upward and its vertex is inside the interval, also evaluate the vertex.
  3. Select the candidate with the smallest function value.

This calculates the quadratic's bounded minimum analytically, subject to floating-point arithmetic. It does not need an initial guess or a search step size.

Apply the method to the original test interval

For f(x) = x2 + 5x + 6, the vertex is xv = -2.5, with f(-2.5) = -0.25. However, the original interval was [-1, 1], which excludes that vertex.

At the interval boundaries, f(-1) = 2 and f(1) = 12. The minimum within the requested interval is therefore 2 at x = -1. The global minimum of -0.25 is a different answer to a different domain question.

Complete MATLAB Function

Save the following in a file named analyzeQuadratic.m. The file name must match the function name. The program accepts real, finite coefficients and a finite interval with its lower bound first.

The third argument controls displayed results: 1 shows the minimum, 2 shows roots and 3 shows both. The returned structure contains the calculated values in every mode, while the graph always displays the polynomial over the requested interval.

function result = analyzeQuadratic(p, bounds, mode)
% Analyze ax^2 + bx + c over a finite interval [L, U].
% mode: 1 = minimum, 2 = roots, 3 = both.

if nargin < 3
    mode = 3;
end

validateattributes(p, {'numeric'}, ...
    {'real','finite','vector','numel',3});
validateattributes(bounds, {'numeric'}, ...
    {'real','finite','vector','numel',2});
validateattributes(mode, {'numeric'}, ...
    {'real','finite','scalar','integer','>=',1,'<=',3});

p = double(p(:).');
bounds = double(bounds(:).');
a = p(1);
b = p(2);
c = p(3);
L = bounds(1);
U = bounds(2);

if L >= U
    error('The lower interval bound must be less than the upper bound.');
end

% Handle quadratic, linear and constant equations separately.
if a ~= 0
    rootValues = roots(p);
    rootStatus = 'Finite roots';
elseif b ~= 0
    rootValues = -c / b;
    rootStatus = 'One linear root';
elseif c == 0
    rootValues = [];
    rootStatus = 'Every real number is a root';
else
    rootValues = [];
    rootStatus = 'No roots';
end

if any(~isfinite(rootValues))
    error('Nonfinite root result. Review coefficient scaling.');
end

% Endpoints always belong to the candidate set.
xCandidates = [L U];
if a > 0
    xVertex = -0.5 * (b / a);
    if isfinite(xVertex) && xVertex >= L && xVertex <= U
        xCandidates = [xCandidates xVertex];
    end
end

yCandidates = polyval(p, xCandidates);
if any(~isfinite(yCandidates))
    error('Function values overflowed. Review coefficients and bounds.');
end

[fMin, index] = min(yCandidates);
xMin = xCandidates(index);

result.coefficients = p;
result.interval = bounds;
result.roots = rootValues;
result.rootStatus = rootStatus;
result.rootResiduals = polyval(p, rootValues);
result.xMin = xMin;
result.fMin = fMin;

if mode == 2 || mode == 3
    disp(rootStatus);
    disp(rootValues);
end
if mode == 1 || mode == 3
    fprintf('Interval minimum: f(%g) = %g\n', xMin, fMin);
end

xPlot = linspace(L, U, 501);
yPlot = polyval(p, xPlot);
if any(~isfinite(yPlot))
    error('Plot values overflowed. Review coefficients and bounds.');
end

figure;
plot(xPlot, yPlot, 'b-', 'LineWidth', 1.5, ...
    'DisplayName', 'Polynomial');
hold on;
plot([L U], [0 0], 'k:', 'HandleVisibility', 'off');

if mode == 2 || mode == 3
    realRoots = real(rootValues(imag(rootValues) == 0));
    visibleRoots = realRoots(realRoots >= L & realRoots <= U);
    if ~isempty(visibleRoots)
        plot(visibleRoots, zeros(size(visibleRoots)), 'ko', ...
            'MarkerFaceColor', 'k', 'DisplayName', 'Real roots');
    end
end

if mode == 1 || mode == 3
    plot(xMin, fMin, 'rs', 'MarkerFaceColor', 'r', ...
        'DisplayName', 'Interval minimum');
end

grid on;
xlim([L U]);
xlabel('x');
ylabel('f(x)');
title('Polynomial roots and bounded minimum');
legend('show', 'Location', 'best');
hold off;
end

The validation uses validateattributes to reject malformed inputs before calculation. A tiny but nonzero leading coefficient is still treated as quadratic; the program does not silently discard it using an arbitrary threshold.

This is an instructional double-precision implementation for reasonably scaled inputs. The finite-value checks catch some overflow cases, but they do not guarantee accuracy for ill-conditioned polynomials or extreme magnitudes.

Run the Original Example

result = analyzeQuadratic([1 5 6], [-1 1], 3);

The expected mathematical results are roots -3 and -2, and a bounded minimum of 2 at -1. Both roots are outside the graph's selected interval, so the command output lists them but the graph contains no root markers.

To include the roots and vertex in the plot, choose a wider interval:

result = analyzeQuadratic([1 5 6], [-4 1], 3);

Now both root locations are visible, and the interval minimum is -0.25 at -2.5. Changing the interval changes the minimization problem; it does not change the polynomial's roots.

The old initial-estimate input has been removed because this calculation does not use an iterative root search. Asking for a value that never affects the answer makes the program harder to understand.

Try Repeated Roots, Complex Roots and Other Cases

CoefficientsIntervalRootsMinimum on the interval
[1 -4 4][0 4]2, repeated.0 at 2.
[1 0 1][-2 2]1i and -1i.1 at 0.
[-1 0 4][-3 2]-2 and 2.-5 at -3.
[0 2 -4][0 3]2, from a linear equation.-4 at 0.
[0 0 5][-1 1]None.5 everywhere on the interval.
[0 0 0][-1 1]Every real number.0 everywhere on the interval.

For a constant function, the program returns the left endpoint as one valid minimizer. It does not mean that the left endpoint is the only minimizer. Similarly, if both endpoints tie for the smallest value, the code returns the first candidate.

The zero polynomial cannot be represented by a finite list of all its roots. That is why the result includes a text status in addition to the numerical root array.

Why a Fixed-Step Search Can Give the Wrong Minimum

The original program examined inputs separated by 0.1. Such a loop finds the smallest sampled value, which is not necessarily the true minimum between samples.

Consider f(x) = (x - 0.03)2. Its exact minimum is zero at 0.03. A grid containing 0 and 0.1 misses the vertex; the value at the nearest of those samples is 0.032 = 0.0009.

For an upward quadratic written as f(x) = a(x - xv)2 + f(xv), a sample displaced by d from the vertex has an excess value of ad2. On a uniform grid that brackets the vertex with spacing h, the nearest sample is at most h/2 away, giving an error bound of ah2/4.

A denser grid improves this sampling approximation, but the vertex formula removes the need for that approximation altogether. Our 501 plotting points draw the curve; they do not determine the reported minimum.

Check Numerical Results Sensibly

You can substitute computed roots back into the polynomial:

p = [1 5 6];
r = roots(p);
residual = polyval(p, r);

Values near zero support the calculation, but an absolute residual should be interpreted in relation to coefficient and root magnitudes. A useful scaled measure is:

eta = |ar2 + br + c| / (|a||r|2 + |b||r| + |c|)

This expression assumes a nonzero denominator. It measures how well a candidate satisfies the equation relative to the sizes of its terms; it is not a universal bound on root-location error.

Repeated and nearly repeated roots are particularly sensitive. For example, changing (x - 2)2 to (x - 2)2 - delta moves its roots to 2 + sqrt(delta) and 2 - sqrt(delta) for positive delta. A small coefficient change can therefore produce a noticeable root separation.

The direct quadratic formula can also lose significant digits when it subtracts nearly equal numbers. For demanding numerical work, consider coefficient scaling, a numerically stable quadratic algorithm or higher precision as appropriate. Do not assume that displaying more decimal places creates additional accuracy.

The plot code marks only roots whose computed imaginary part is exactly zero. If roundoff gives a theoretically real root a tiny imaginary part, inspect the scale and residual before applying a justified display tolerance. Blindly discarding all imaginary parts would incorrectly place complex roots on the real graph.

When Would You Use fminbnd Instead?

For more general scalar functions, fminbnd searches for a local minimum between finite bounds. It does not guarantee the global minimum when multiple local minima exist, and you should evaluate interval endpoints separately when solving a closed-interval problem.

For our quadratic, checking the vertex and endpoints is simpler and directly follows the mathematics. An iterative optimizer adds work without improving the underlying model.

Review of the Program

We represent the function with three coefficients, calculate its roots and find the bounded minimum from a small set of candidates. The program plots real roots at (root, 0) and the minimum at (xMin, fMin). It also separates calculation from display choices, so changing the mode does not change the numerical problem.

Use the examples as expected mathematical answers when running the function in your own MATLAB installation. Comparing several different cases is more informative than checking only one upward-opening parabola.

Frequently Asked Questions

Why are my roots missing from the graph?

They may be complex or outside the plotting interval. The program reports all finite roots but only marks real roots inside the displayed interval.

Why is the minimum not located at a root?

A root is where the function equals zero. A minimum is where it reaches its smallest allowed value. Those locations coincide only for particular functions and domains.

What happens if the coefficient of x squared is zero?

The equation is linear when the coefficient of x is nonzero, and constant otherwise. The code handles these cases without dividing by the quadratic coefficient.

Do I need an initial guess?

No. This program uses polynomial roots and an analytic quadratic minimum calculation, so there is no initial-guess input.

Does a downward-opening quadratic have a minimum?

It has no finite global minimum over the entire real line. On a finite closed interval, it does have a minimum at one or both endpoints.

Can I use this function for a cubic?

No. MATLAB's roots function supports higher-degree polynomials, but this tutorial's minimum calculation is specific to degree two or less. A cubic needs its own stationary-point analysis and endpoint checks.


Comments

0

Join the conversation