To compute the intersection(s) of the graphs of the exponential function 'y=e^x' and the line 'y=mx+b' (as already noted in the first answer to this question), it is convenient to consider the function 'f(x)=e^x-mx-b'. Since 'f' is strictly convex, it has at most two roots. Next, depending on the sign of 'm', we determine how many roots are possible and, if there are two, we bracket them. Then the roots are computed using the bisection method. This is exactly the approach implemented in the code below. I added two more examples to illustrate an important point: the roots exist, but they lie outside our interval.
\documentclass[tikz,border=1cm]{standalone}
\usepackage{luacode}
\begin{luacode*}
-- Compute intersections of y=exp(x) with y=m*x+b on [xmin,xmax]
-- Export x-roots into TeX macro \roots (empty if none).
function lineExpIntersections(m,b,xmin,xmax)
local function f(x) return math.exp(x) - (m*x + b) end
local function bisect(L,R, tol, maxit)
tol = tol or 1e-6
maxit = maxit or 60
local fL, fR = f(L), f(R)
if fL*fR > 0 then return nil end
for _=1,maxit do
local M = 0.5*(L+R)
local fM = f(M)
if (R-L) < tol then return M end
if fL*fM < 0 then
R, fR = M, fM
else
L, fL = M, fM
end
end
return 0.5*(L+R)
end
local roots = {}
if m < 0 then
-- strictly increasing => at most one root; find it if bracketed
local r = bisect(xmin, xmax)
if r then roots[#roots+1] = r end
elseif m == 0 then
-- exp(x)=b
if b > 0 then
local r = math.log(b)
if r >= xmin and r <= xmax then roots[#roots+1] = r end
end
else
-- m>0: 0/1/2 roots; minimum at x0=log(m)
local x0 = math.log(m)
local fmin = m - (m*math.log(m) + b) -- f(x0)
if fmin == 0 then
if x0 >= xmin and x0 <= xmax then roots[#roots+1] = x0 end
elseif fmin < 0 then
-- two roots globally; try to bracket each inside [xmin,xmax]
local L1, R1 = xmin, math.min(x0, xmax)
local L2, R2 = math.max(x0, xmin), xmax
local r1 = bisect(L1, R1)
local r2 = bisect(L2, R2)
if r1 then roots[#roots+1] = r1 end
if r2 then roots[#roots+1] = r2 end
end
end
local out = {}
for i=1,#roots do out[i] = string.format("%.12f", roots[i]) end
tex.sprint("\\def\\roots{" .. table.concat(out, ",") .. "}")
end
\end{luacode*}
% TeX wrapper: defines \roots
\newcommand{\LineExpIntersections}[4]{%
\directlua{lineExpIntersections(#1,#2,#3,#4)}%
}
\begin{document}
\begin{tikzpicture}
\draw[->] (-2,0) -- (2,0);
\draw[->] (0,-2) -- (0,{exp(2)});
\draw[domain=-2:2,samples=200] plot (\x,{exp(\x)});
\def\xmin{-2}
\def\xmax{2}
% 1) y = x + 1.5 (two intersections)
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x+1.5});
\LineExpIntersections{1}{1.5}{\xmin}{\xmax}
\foreach \r in \roots { \fill[red] (\r,{exp(\r)}) circle (1.2pt); }
% 2) y = x + 1 (one intersection)
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x+1});
\LineExpIntersections{1}{1}{\xmin}{\xmax}
\foreach \r in \roots { \fill[green] (\r,{exp(\r)}) circle (1.2pt); }
% 3) y = -x + 4.5 (one intersection)
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{-1*\x+4.5});
\LineExpIntersections{-1}{4.5}{\xmin}{\xmax}
\foreach \r in \roots { \fill[blue] (\r,{exp(\r)}) circle (1.2pt); }
% 4) y = x (zero intersections)
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x});
\LineExpIntersections{1}{0}{\xmin}{\xmax}
\foreach \r in \roots { \fill (\r,{exp(\r)}) circle (1.2pt); }
% 5) y = x + 4 (zero intersections)
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x+4});
\LineExpIntersections{1}{4}{\xmin}{\xmax}
\foreach \r in \roots { \fill[orange] (\r,{exp(\r)}) circle (1.2pt); }
% 6) y = x + 5 (no intersections on [xmin,xmax]” или “roots outside the interval)
\def\txmax{1.5}
\draw[domain=\xmin:\txmax,samples=2] plot (\x,{1*\x+5});
\LineExpIntersections{1}{5}{\xmin}{\txmax}
\foreach \r in \roots { \fill[orange] (\r,{exp(\r)}) circle (1.2pt); }
\end{tikzpicture}
\end{document}
P.S. If 'm' or 'fmin' is obtained as the result of computations, an “exactly zero” comparison may fail. In our examples everything is fine, but in the general case one should use something like 'if math.abs(m) < eps then ...', and so on.

Edit.
I slightly modified the stopping criterion for the bisection method. If the interval length 'R-L' becomes smaller than 'tol=10^{-6}', we stop and return the midpoint of the interval '[L,R]'. If, for some reason, we do not reach the desired accuracy in x within 'maxit=60' steps (a generous margin), the function returns the midpoint of the last interval.
Edit 2.
I added to my code the ability to choose between two methods for approximating the roots: the bisection method and Newton’s method. The choice can be made once for all examples, as in the code, or you can choose one of the two methods separately for each example. Alternatively, you can run each example twice, once with each method, and compare the results.
\documentclass[tikz,border=1cm]{standalone}
\usepackage{luacode}
\begin{luacode*}
-- Compute intersections of y=exp(x) with y=m*x+b on [xmin,xmax]
-- method = "bisection" or "newton"
-- Export x-roots into TeX macro \roots (empty if none).
function lineExpIntersections(m,b,xmin,xmax, method)
method = method or "bisection"
local function f(x) return math.exp(x) - (m*x + b) end
local function df(x) return math.exp(x) - m end
local function bisect(L,R, tol, maxit)
tol = tol or 1e-6
maxit = maxit or 60
local fL, fR = f(L), f(R)
if fL*fR > 0 then return nil end
for _=1,maxit do
local M = 0.5*(L+R)
local fM = f(M)
if (R-L) < tol then return M end
if fL*fM < 0 then
R, fR = M, fM
else
L, fL = M, fM
end
end
return 0.5*(L+R)
end
-- Plain Newton on [L,R], starting from an endpoint (no fallback).
local function newton(L,R, tol, maxit)
tol = tol or 1e-6
maxit = maxit or 30
local fL, fR = f(L), f(R)
if fL*fR > 0 then return nil end
-- start from the endpoint with smaller |f|
local x = (math.abs(fL) <= math.abs(fR)) and L or R
-- if derivative is too small at chosen endpoint, try the other one
if math.abs(df(x)) < 1e-15 then
x = (x == L) and R or L
if math.abs(df(x)) < 1e-15 then return nil end
end
for _=1,maxit do
local fx = f(x)
if math.abs(fx) < tol then return x end
local dfx = df(x)
if math.abs(dfx) < 1e-15 then return nil end
local xnew = x - fx/dfx
if xnew <= L or xnew >= R then return nil end
x = xnew
end
return nil
end
local function solve_on_interval(L,R)
if method == "newton" then
return newton(L,R, 1e-6, 30)
else
return bisect(L,R, 1e-6, 60)
end
end
local roots = {}
if m < 0 then
local r = solve_on_interval(xmin, xmax)
if r then roots[#roots+1] = r end
elseif m == 0 then
if b > 0 then
local r = math.log(b)
if r >= xmin and r <= xmax then roots[#roots+1] = r end
end
else
local x0 = math.log(m)
local fmin = m - (m*math.log(m) + b) -- f(x0)
if fmin == 0 then
if x0 >= xmin and x0 <= xmax then roots[#roots+1] = x0 end
elseif fmin < 0 then
local L1, R1 = xmin, math.min(x0, xmax)
local L2, R2 = math.max(x0, xmin), xmax
local r1 = solve_on_interval(L1, R1)
local r2 = solve_on_interval(L2, R2)
if r1 then roots[#roots+1] = r1 end
if r2 then roots[#roots+1] = r2 end
end
end
local out = {}
for i=1,#roots do out[i] = string.format("%.12f", roots[i]) end
tex.sprint("\\def\\roots{" .. table.concat(out, ",") .. "}")
end
\end{luacode*}
% TeX wrapper: #5 is method: bisection/newton
\newcommand{\LineExpIntersections}[5]{%
\directlua{lineExpIntersections(#1,#2,#3,#4,"#5")}%
}
\begin{document}
\begin{tikzpicture}
\draw[->] (-2,0) -- (2,0);
\draw[->] (0,-2) -- (0,{exp(2)});
\draw[domain=-2:2,samples=200] plot (\x,{exp(\x)});
\def\xmin{-2}
\def\xmax{2}
% Choose one:
%\def\method{bisection}
\def\method{newton}
% 1) y = x + 1.5
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x+1.5});
\LineExpIntersections{1}{1.5}{\xmin}{\xmax}{\method}
\foreach \r in \roots { \fill[red] (\r,{exp(\r)}) circle (1.2pt); }
% 2) y = x + 1
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x+1});
\LineExpIntersections{1}{1}{\xmin}{\xmax}{\method}
\foreach \r in \roots { \fill[green] (\r,{exp(\r)}) circle (1.2pt); }
% 3) y = -x + 4.5
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{-1*\x+4.5});
\LineExpIntersections{-1}{4.5}{\xmin}{\xmax}{\method}
\foreach \r in \roots { \fill[blue] (\r,{exp(\r)}) circle (1.2pt); }
% 4) y = x
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x});
\LineExpIntersections{1}{0}{\xmin}{\xmax}{\method}
\foreach \r in \roots { \fill (\r,{exp(\r)}) circle (1.2pt); }
% 5) y = x + 4 (root outside [-2,2])
\draw[domain=\xmin:\xmax,samples=2] plot (\x,{1*\x+4});
\LineExpIntersections{1}{4}{\xmin}{\xmax}{\method}
\foreach \r in \roots { \fill[orange] (\r,{exp(\r)}) circle (1.2pt); }
% 6) y = x + 5 (no intersections on [-2,1.5])
\def\txmax{1.5}
\draw[domain=\xmin:\txmax,samples=2] plot (\x,{1*\x+5});
\LineExpIntersections{1}{5}{\xmin}{\txmax}{\method}
\foreach \r in \roots { \fill[yellow] (\r,{exp(\r)}) circle (1.2pt); }
\end{tikzpicture}
\end{document}
intersections? note that the code there usesfpuin places to avoid problems withpgfmath, so trying to do it with the latter may be problematic. (but I would preferl3fptofputhese days.)pgfmath. b/c then you would need to do something to reduce the chances of exceeding tex's max dimension and also think about whether it is accurate enough. a lua solution is different: you do not have to think about the limitations of tex arithmetic in that case and starting from the maths makes more sense. I mean, I wouldn't start from that library, but I would not try to usepgfmath;).