Learning Objectives
After this section you will be able to:
- State the three conditions that must ALL hold for to be continuous at a point .
- Diagnose which of the three conditions fails for a given discontinuity.
- Distinguish a hole (Condition 1), a jump (Condition 2), and a mismatched dot (Condition 3) by looking at a graph.
- Implement the three-condition test in plain Python and in PyTorch.
- Apply the test by hand to a small family of functions without software.
Why We Need a Formal Test
In §3.1 we described continuity with an evocative picture: you can sketch the graph without lifting your pencil. That metaphor is perfect for a quick feel, but it is hopeless as a test. Does the graph of count? Your pen would blur into noise near the origin. Does the graph of a function defined only on the rationals count? You can't draw it at all. We need a test that doesn't rely on anyone's drawing hand.
That test is the subject of this section. It has exactly three parts, and each part plugs directly into the language of limits we developed in Chapter 2. The beauty of the test is that the three parts are INDEPENDENT — each can fail on its own, each produces a different visual signature in the graph, and each can be detected numerically.
Continuity at a point is a contract between three quantities: , , and . Continuity says all three exist and are equal. Break any one of the three, and the contract is broken.
The Three Conditions — Stated
Definition 3.2.1 — Continuity at a Point
A function is continuous at if and only if all three of the following hold:
If any one of (1), (2), (3) fails, we say is discontinuous at .
Logicians love this definition because it packs a lot of machinery into three short lines. Condition 1 invokes the domain of . Condition 2 invokes the entire - theory of limits. Condition 3 links the two worlds — the value of at a single point must agree with the trend of around that point.
The next three subsections walk through each condition in turn.
Condition 1 — Must Be Defined
This is the most primitive of the three: before we can even talk about continuity at a point, the function must actually produce a value there. The point must be in the domain of .
The canonical failure mode is a removable singularity — a single isolated point where the formula produces , a square root of a negative, a logarithm of zero, or any other forbidden operation.
Plug in every number except 3 and you get a sensible output — in fact you always get , because . Plug in 3 and you are handed . Condition 1 fails on sight: there is no .
A subtlety
The two-sided limit as DOES exist — it is 6 (both sides point there). So conditions 2 and 3 can't even be evaluated in the usual sense; the function is not continuous at 3 purely because it doesn't live at 3. We call this a removable discontinuity because if we redefine the function to equal 6 at the missing point, we glue the hole shut and recover continuity.
Condition 2 — The Limit Must Exist
Even if is perfectly well defined, continuity further demands that the function have a consistent target as inputs approach . Formally, both one-sided limits must exist and agree:
The classic failure is a jump discontinuity: a piecewise-defined function whose left and right pieces disagree at the joint. Consider
Condition 1 passes: . But as climbs toward 2 from the left, the outputs approach ; as it descends from the right, the outputs approach . Two one-sided targets, no single two-sided target, no limit. Condition 2 fails.
Don't confuse blow-up with a jump
A second way Condition 2 can fail is if either one-sided limit is infinite — think of near . Even though the limit in some loose sense “is ”, our definition demands a finite . Infinite limits are discussed in §2.4 and §3.3; for continuity they are just another way Condition 2 fails.
Condition 3 — The Two Must Match
Here is the most subtle condition. Even if exists and the two-sided limit exists, continuity further requires the two to be EQUAL. The trend and the value must agree on the same number.
It sounds like this should be automatic — and for “nice” functions it is — but a sadistic textbook author can easily break it with a single line of piecewise definition:
Everywhere except the single input 1, this is the innocuous line . The two-sided limit as is . But the value has been artificially set to . Conditions 1 and 2 pass; Condition 3 fails because . Graphically, a filled dot floats one unit above the line at a single point.
Why this matters
Condition 3 is exactly what lets calculus be local. If you know the function near a point and you know the function AT a point, continuity says those two pieces of information cannot contradict each other. The derivative, the integral, and every approximation theorem depends on this agreement.
Interactive — Continuity Tester
Pick a scenario. Shrink the probe distance to sub-pixel precision. The panel below the plot reports, in real time, which of the three conditions pass and which fail. Each scenario is rigged so that a DIFFERENT condition is the one that breaks — verify this for yourself by reading the verdict.
How to read the panel
Each condition shows a green ✓ (passing), a red ✗ on the actual failer, and a grey ✗ on conditions that can't even be tested because an earlier one failed. The verdict at the bottom names the specific reason the function is (or isn't) continuous.
Interactive — Drag the Point
The previous tester is fixed: you cannot change what is. Here we flip that — the line is locked as with a hole at , and YOU get to drag the filled dot (that is, ) up and down. Condition 3 flips the moment the dot leaves the line.
This demo is the cleanest possible picture of Condition 3: the limit is the target the function is heading toward; the dot is the value we chose to put at . Continuity is the demand that target and value coincide. Everything else — jumps, holes, asymptotes — boils down to this alignment, possibly with one of its operands missing.
Numerical Table Check
Before touching software, let us rehearse the three-condition check by hand on our four scenarios. Each row reports what each condition sees; the final column records the verdict.
| Scenario | f(a) | left limit | right limit | Condition failed | Continuous? |
|---|---|---|---|---|---|
| f(x) = (x²−9)/(x−3) at a = 3 | undefined | 6 | 6 | 1 | no |
| g(x) piecewise at a = 2 | 3 | 3 | 4 | 2 | no |
| h(x) = x+3, h(1) = 5 at a = 1 | 5 | 4 | 4 | 3 | no |
| p(x) = x² + 1 at a = 2 | 5 | 5 | 5 | none | yes |
Each row lines up with a button in the interactive tester above. The numbers in the middle columns are what the sliders report as you shrink . Reading the table horizontally is exactly the three-condition test: look at , then check the two one-sided limits, then compare them to .
Worked Example — By Hand
Let us commit one of the scenarios to paper and execute the test step-by-step. We take the mismatch scenario because it exercises all three conditions: two pass, one fails.
Click to expand — apply the three-condition test to at
We want to decide whether is continuous at . We must verify all three conditions; a single failure kills continuity.
The piecewise definition gives us directly. Condition 1 passes.
Because every nearby input satisfies , the value of on those inputs is exactly . So
Both one-sided limits equal 4, so the two-sided limit exists and equals 4. Condition 2 passes.
The limit insists the function is heading toward 4, but the value we have chosen at is 5. Condition 3 fails.
Self-check
Redo the same three-step check on the polynomial at . You should find: , , and they match — so is continuous at 2. This is the positive control that confirms the test works on continuous functions too, not just on pathological ones.
Python — The Three-Condition Checker
We now convert the test into code. The goal is to build a single function, is_continuous_at, that takes any scalar function and any point, and returns each of the three verdicts plus the overall call. We then run it on the four scenarios from the interactive tester. Click any line of code to see the exact values flowing through it.
The four output lines line up exactly with the four scenarios of the interactive tester — hole fails Condition 1, jump fails Condition 2, mismatch fails Condition 3, polynomial passes all three. No calculus was required at runtime; the function did the detective work by poking at the three predicates.
Numerical caveat
A finite probe distance can mis-diagnose wildly oscillating functions (think near 0): at some small but non-zero , the left and right probes might accidentally agree even though the true limit does not exist. Our plain-Python checker will happily report continuity in that case — wrongly. The formal - definition closes this loophole; numerical probes cannot.
PyTorch — Checking Many Points at Once
The plain-Python checker handles one point per call. What if we want to scan a thousand candidate points and find all the discontinuities? A Python loop would work but would be slow. PyTorch lets us probe every candidate in a single tensor operation. We demonstrate on the jump scenario: the checker must flag as discontinuous while passing all other candidates.
Why this matters later
This is the same mental move that lets training neural networks scale: instead of looping in Python, put your data into a tensor and let the framework broadcast. Continuity checks are trivial, but the pattern — evaluate at many shifted inputs, take element-wise differences, compare against a tolerance — is EXACTLY how finite- difference gradient checks, Lipschitz estimators, and many numerical calculus primitives work in practice.
Common Pitfalls
- Confusing “the limit exists” with “the function is continuous”. A function can have a perfectly good limit at and still be discontinuous there — either because is undefined (Condition 1) or because (Condition 3).
- Thinking piecewise always means discontinuous. Not at all. is defined piecewise (it is for and for ) yet is continuous everywhere because at the joint both pieces evaluate to 0. The joint is where continuity must be CHECKED, not where it is automatically broken.
- Dismissing Condition 3 as pedantic. It is exactly Condition 3 that breaks when you override a function's value at a single point — and that override is what distinguishes removable from essential discontinuities (§3.3). Without Condition 3 we could not classify discontinuities at all.
- Forgetting that infinite limits don't count. Condition 2 requires to be a finite real number. “Goes to infinity” is not a limit in the sense of this definition — it is a vertical asymptote, and the function is discontinuous there.
- Trusting a numerical check alone. Our Python probe at can be fooled by pathological oscillation. Numerical continuity checks are a useful smoke test; they are not proofs. The formal - definition is.
Summary
- Continuity at a point is defined by three conditions: is defined, exists, and the two are equal.
- Each condition fails with its own visual signature — Condition 1 is a hole, Condition 2 is a jump (or a blow-up), Condition 3 is a misplaced dot.
- The test is straightforward to run both by hand and in code. Plain Python implements it one point at a time; PyTorch vectorises it across any number of candidates at once.
- Numerical checks with a finite probe can be fooled by wild oscillation; the formal definition is what ultimately protects us.
What's next
§3.3 uses these three conditions to classify discontinuities: removable, jump, infinite, and oscillating. Each class corresponds to a specific pattern of passing and failing conditions, and each motivates a different repair strategy.