May seem strange as I’m good in programming, but I just started diving into math. ATM I’m learning combinatorics at Khan Academy, and here’s an example of a question that I struggled with (that’s not the question):
The answer to «ways of getting 1 head in 4 flips» is 4 (HTTT, THTT, TTHT, TTTH). But let’s put it the other way round: «ways of getting 3 tails in 4 flips» (which is, obviously, the same question). It would be the number of places to put it: 4×3×2=24, next divided by 3 to remove duplicates (i.e. TTTH is counted 3 times): 24/3=8. But 8≠4! We used right calculations, reasoning, and got absolutely different answer, how is that possible?
I thought: there must be generic ways of debugging math problems, i.e. not just directly solving, but rather finding the problem when everything supposed to work, but it doesn’t. I tried searching, and to my surprise found nothing, like nobody ever asked the question. Well, here’s mine:
What are common ways to debug math problems; both generic and specialized would be nice to know. If you know any relevant articles, I’d be glad to read it too.
As a comp sci major who dabbles in math, let me throw my perspective into this.
Debugging math is a completely different experience from debugging programs. The difference is that while we have programs, they (tend to be) imperative – that is, they list out a series of steps that need to be followed.
(I know that this is a gross generalization, and that Haskell/LISP/Scheme/Functional Programming languages exist and they aren’t that way, but most “general” programming languages are imperative.)
In math, you generally have a set of statements that you “bring together” to get a solution. It’s more of an expression than a recipe if that makes sense to you.
However, the nice part is a lot of the intuition of debugging carries over.
Some principles that carry over very nicely:
Isolate a problem, get the minimal failing example. This works in both math and compsci. If you have a general formula, substitute small values like 0, 1, etc. as a sanity check.
Breaking things gives you a better understanding of how they work. When you read a theorem or code anything, always push the boundaries of what you’re doing. Ask yourself – “what would happen if I do not have this statement in my proof”? “What if I eliminate this line”? “Is this assumption really necessary”? Playing with math and trying to break it often helps in learning it as well.
Also, some branches of math are just straight up weird, and require you to build intuition about them – You won’t find the ideas intuitive at all when you begin (topology was like this for me when I began learning it), but you gradually pick up styles of thinking that complements the branch of math you’re studying.
Another great “debugging tool” is to plug in good examples into theorems / problems whenever you face something too generic. Always arm yourself with at least 3 to 4 examples for any topic, so you can quickly fact-check about things (and refer back to those examples). It’s also nice to have non-examples to things to know the difference.
If you’ve taken calculus, then knowing your examples would be
- a function that is discontinuous f(x)=floor(x)
- a continuous but not differentiable function – f(x)=|x|
- a function that is both continuous and differentiable – f(x)=sinx
- a nowhere differentiable function – Weierstrass function
- a nowhere continuous function – Conway’s base 13 function
There are books such as counterexamples in topology that will arm you with a whole bunch of examples to think about. Things like these are super useful the more abstract you get in math.
One last thing you can do as a programmer is to actually write code that checks a hunch you have – this is a huge advantage and don’t be afraid to exploit this. Think something is true but feel too lazy to check it? Code it! It’s not only practice, but it often teaches you some really cool math facts as well.
Hope this helps as a rough guide on how to debug math 🙂