Coding Horror: Should Competent Programmers be "Mathematically Inclined"?
codinghorror.com
codinghorror.com
Being "mathematically inclined" does not mean being well educated in mathematics. You don't need to be able to rigorously prove the fundamental theory of calculus to be a good programmer. Most of mathematics does not directly apply to programming but the thought processes are extremely similar. If you see someone sorting papers and try to figure out why they are doing it inefficiently, that is mathematical inclination. Its about thinking in algorithms, not mastering differential equations.
He's created the strawman that a strong mastery of mathematics is required for competent programming. That is not whats been said. A strong mathematical inclination is a way of looking at problems that programmers and mathematicians share. Its about seeing "through" problems and finding solutions. Its about reducing problems to previously solved problems (or simpler versions of themselves), etc. I can list a dozen ways in which programmers and mathematicians do similar things.
But, playing along with the strawman, real math becomes necessary in normal programming fairly often. Not 3d, Jeff, even 2d. What's the distance between a point and a line segment?
Not really, I would say it was a logical inclination not necessarily a mathematical one. And therein is the rub I see programming as logic and problem solving with little to no inherent math unless I am dealing with a mathematical problem. Kind of like the way writing books is not an inherently mathematical in nature even if quite a bit of math is involved in writing a mathematics text book.
George Boole was a mathematician. The logic textbooks are full of words that betray their background, e.g. the "lambda calculus". All of these things have their roots in mathematics. And before there was computer science degrees, these things -were- mathematics.
I doubt, very seriously, that Djikstra would draw much of a distinction between "logical inclination" and "mathematical inclination". So while you might, the original context of the quote in question needs to be considered.
Oddly, a study that is all about exploration of ideas and abstraction has been narrowly defined in many people's minds. Hopefully mathematics educators can break these limited views in years to come.
Logic is the study of the principles of valid demonstration and inference. Logic is a branch of philosophy, a part of the classical trivium, as well as a branch of mathematics.
In fact, in universities, logic (formal logic, with symbols) is usually taught by philosophy departments.
I've only worked with one philosopher. He's very creative and produces reams of working code, but new requirements always mean new reams of code. Everyone suspects there must be a lot of redundancy in his code, but then, nobody has needed to look, because it all works....
Most or all undergrad pure logic classes, as far as I've ever seen. There aren't usually a whole lot of pure logic classes, so it's entirely possible that your school(s) might only have had one.
Philosophers deal with words.
Philosophers deal with logic in arguments. I took a couple logic classes during my undergrad and they were entirely symbolic logic. I also took a couple philosophy classes, and they used symbolic logic extensively to describe the flow of logic in arguments. Skimming through MIT OpenCourseWare indicates it's similar there: http://is.gd/qaE0
If you take a graduate-level math class in logic ... even if you just take an upper-division set theory class, you'll learn more about mathematical logic
So you are saying that heavily mathematical logic is more heavily mathematical? Interesting. Do you also learn about tautologies in these classes?
I'm guessing that you are actually implying that mathematical logic is more useful to programmers. As I stated elsewhere, during my undergrad I took classes that touched on both philosophical and mathematical logic concepts and I definitely find myself using both. In my experience: symbolic/philosophical concepts in high level development, symbolic/mathematical concepts in low level development.
I'm not saying that mathematical logic is more heavily mathematical, I'm saying that philosophers are only interested in mathematical logic concepts they can extract from their mathematical context and apply in words. Aside from that, they are not interested in mathematical logic at all. Whether they are interested in mathematically defined concepts such as "complete," "consistent," and so forth depends entirely on whether the concepts have suggestive names that seem to imbue mathematical results with meanings beyond mathematics.
The point is that logic used in computer science/information science is a hybrid that is informed by other forms of logic (including linguistics), not just math.
I'm saying that philosophers are only interested in
I don't know what philosophers are only interested in because I don't know what a "philosopher" is.
As for what a philosopher is, we're all philosophers, but not all of us get paid for it.
However, least see what happens when one does not apply mathematical thinking into his own reasoning. I do it myself from time to time and refer to it as my "rat intelligence". You go over and over the facts, one at a time, trying to figure out the way out... It feels pretty much like a rat walking through a maze inside of my brain.
But it comes to a point, when the problem is very hard, that no matter how many times the rat goes over and over the same data, it does not find the answer. In that case you need a superior type of reasoning. You need to step aside and look at the problem as a whole. To find patterns that you can abstract out and rephrase the problem in a way more tractable. And I think in this broader sense logic and math use the same type of mental tools (principles) to attack the same issues.
Logic is a strange area since it bridges fields, primarily math, philosophy, linguistics and computer science.
In my experience, designing software more frequently taps into logic as applied to philosophical arguments and conceptual formal logic more than heavily mathematical areas of logic. The reason is that creating software is basically the process of taking something from the real world and reducing it to a series of logical components and relationships. This is pretty much the exact process for applying formal logic to philosophical questions.
On the other hand, actually coding the software taps far more into the mathematical and linguistic aspects of formal logic, since it's involves piecing together units of mathematical logic to construct a logical machine.
In practice, this whole process is obviously more nuanced, interconnected and filled with gray areas.
It's also certainly possible to argue that all reasoning is math, but this isn't a new concept and dates back to Plato.
This topic seems to come up relatively frequently, and I appreciate Jeff's attempt to add to the conversation with some interestingly selected quotes. Still, the above quote to me highlights how many people, including Jeff, vastly oversimplify the math side of the equation. To put lbrandy's comment slightly differently, knowing a large number of mathematical facts will not make you a good programmer. But to me a basic explanation of “mathematical inclination” could be: a strong understanding of how a mathematical system is governed by rules, and how a problem can be parsed, compartmentalized, and addressed in pieces. It seems fairly self-evident to me that those skills would be shared by anyone whol could be described as even a competent programmer.
I think I agree with you. I would argue that the mathematical ability needed to solve the question above is to realize how to phrase a query to google, find the resulting formula, and turn it into code. You don't need to be able to derive it, for the vast majority of jobs out there.
Also: I've noticed that most programming is equivalent to what in grade school and high school they called a "word problem". Most of the class would groan when we had to do these; I loved them. I suspect if you struggled with word problems, you would have a hard time programming.
You left out the part where, months later, you pay a mathematically-inclined consultant hundreds of dollars to fix the bugs in the formula that you cut and pasted without understanding it. ;)
Numerical methods was a very interesting class, even on day one. You'd be amazed how easy it is to screw up simple formulas by doing the math in the wrong order -- the finite precision of floating-point arithmetic means that you have to be constantly on your guard.
Does anyone have an elegant solution?
Between any arbitrary point on a line segment, the point on the line segment that contains the shortest point, and the point in question, you have a triangle.
You can take the length between any point on the line segment and the point in space, find it's magnitude squared, and subtract the magnitude squared of it's projection along the line segment. This gives you the distance of between the point and line segment squared by pythagoras' theorem.
x
/|
/ |
/ |
-a****-----
a is the arbitrary point on the line, the *s are the projected segment, and x is the point you want to find the distance from.let A, B be the 2D start and end points of a line segment. Let P be a 2D point.
We think about the problem and graph the problem like this:
P
.
A ------------------------ B
Then we realize that we can re-frame the problem in terms of a right triangle: P
.
/ |
/ |
/ _|
/ | |
A ------------------------- B
Q
Now for some definitions. Let's define the vector operations that we'll be working with. class Vec2( object ):
def __init__( self, x, y ):
self.x = x
self.y = y
This represents a 2D vector with properties 'x' and 'y'. def length( V ):
return sqrt( V.x*V.x + V.y*V.y )
This computes the length of a 2D vector. def normalize( V ):
V_len = length( V )
return Vec2( V.x / V_len, V.y / V_len )
This computes a new vector that points in the same direction as V, but is of unit length ( length( normalize( V ) ) == 1.0 ). def dot( V1, V2 ):
return V1.x*V2.x + V1.y*V2.y
This computes the "dot product" between two vectors. I'll clarify this operation in a moment.Finally, for clarity and succinctness:
V1 + V2 represents Vec2( V1.x+V2.x, V1.y+V2.y )
V1 - V2 represents Vec2( V1.x-V2.x, V1.y-V2.y )
S * V represents Vec2( S*V.x, S*V.y ), which
scales the vector V by a factor of S. So (2.0 * V)
would result in a vector in the same direction as V,
but twice as long.
Goal: find the length of PQFirst, we examine our graph above and write out the known and unknown quantities.
AB = B - A
AP = P - A
AB_len = length( AB )
AP_len = length( AP )
Q = ?
AQ = Q - A
PQ = P - A
It looks like our first step is to compute Q.A dot product trick
The trick we'll use to solve this is via the following rule:
For any line that passes through A and B, dot( normalize( B - A ), P - A ) is the distance between A and the closest point on the line to P.
Huh?
Let me explain this thoroughly, so you can add it to your own toolbox for your entire life.
Building an intuitive understanding of vector math
Imagine a line segment AB and a point P. Now picture point Q, which is the closest point to P on a line that passes through A and B, just like the graph above. You can use the dot product to find the distance between A and Q.
First, compute the vector AB by computing (B - A).
You can visualize this as follows. Picture a line segment from point A to point B. Now move it so that A is coincident with the origin (0,0). Since you moved it, you didn't change its length and you didn't change its direction, just its location. So the result of (B - A) could be intuitively described as "a line segment that begins at the origin (0,0) whose length and direction are equal to AB's".
The next step in the dot product trick is to set the length of (B - A) to 1.0, which is "unit length". A few related trivia notes:
- if a vector's length is exactly 1.0, then it is called a "unit vector".
- when you set a vector's length to 1.0, you have just "normalized" the vector.
- normalized vectors are a succinct way to represent a direction in space, whether it be 1D, 2D, 3D, or any other D.
- remember the 2D line equation "y = mx + b"? 'm' is the line's slope. In 2D space, slope is just an alternate way of representing a vector's direction. You can compute a vector V's slope as "rise over run" (V.y / V.x). The only advantage of using slope to represent a direction in 2D is that it's efficient to compute and to use. There are two big disadvantages. First, it's not immediately clear how we'd compute slope in 3D. But more importantly, you can't represent vertical lines with a slope. A vertical line has no 'run', so (V.x / 0.0) == undefined. In programming terms, this could cause problems. So slope is generally avoided for those reasons. I explained it here because I am hoping that it helps you to understand vectors more intuitively.
So, let's enumerate some features of unit length vectors:
- they can be used to represent any direction in space.
- the range of each component of a unit length vector is never outside of [-1.0 .. 1.0].
- if you compute the dot product between a unit length vector and a point, you have projected the point onto the vector. The result of the dot product is the distance between the origin and the closest point on the vector. -- dot product trick
- the dot product of two unit length vectors is equal to the cosine of the angle between them. In other words, let V1 and V2 be unit length vectors. dot( V1, V2 ) == cos( angle between V1 and V2 ). Related facts:
-- the dot product of two unit length vectors is always in the range [-1.0 .. 1.0].
-- if V1 points in the same direction as V2 (that is, V1 == V2), then the dot product is 1.0.
-- if V1 is perpendicular to V2, then the dot product is 0.0.
-- if V1 points in the opposite direction of V2 (that is, V1 == -V2), then the dot product is -1.0.
-- And now, for something fun (and totally optional -- if you don't really understand, don't sweat it. But hopefully it will be interesting rather than confusing): Imagine a light bulb at point L. Now imagine a sphere at point S, being lit by that light bulb. Imagine a point on that sphere, P. You can compute the lightbulb's effect on the sphere at that point as follows:
L = lightbulb position
S = sphere position
P = point on sphere
Ldir = normalize( L - P )
surface_normal = normalize( P - S )
light_intensity = max( 0.0, dot( surface_normal, Ldir ) )
# that quanitity is called "NdotL" in computer graphics.
# you would then multiply that quantity by the light's
# "attenuation", which dims the light as it gets further
# away. But that's outside the scope of this example.
# If you're interested in computer graphics,
# the book "Realtime Rendering" is fantastic.
Solving the problem, finally.So, let's use our newfound ninja-guru knowledge of vectors and dot products to solve the original problem. After glancing at the above graph again, we remember we need to compute the length of the line segment PQ. One way to solve it is to compute the point Q, then length( Q - P ) is our answer. Getting down to business:
def dist_point_to_line( A, B, P ):
# represent the line segment AB as a vector.
AB = B - A
# determine the direction of B relative to A.
AB_dir = normalize( AB )
# compute the distance between A and Q using the dot
# product trick. The first argument is a unit length
# vector. The second argument is a point *relative to
# that vector*.
AQ_len = dot( AB_dir, P - A )
# Now that we know the length of AQ, we can compute Q.
# To do this, think of the following equation as "start
# at A; move along the direction AB_dir by AQ_len units;
# that position is Q."
Q = A + AQ_len * AB_dir
# return the length of PQ.
return length( Q - P )
I hope the explanation was been illuminating, and not too confusing. If you have any questions, feel free to ask.I'll only add that they are called versors and one can read more about their magic in any material about quaternions.
Luckily, since you know some math, and you understand what a dot product is, and how it relates to a projection, you can trivially extend your solution by checking to make sure Q is on AB, and then adjusting your answer if its not.
:)
This has the advantage that it generalizes to arbitrary dimensions. For example, you can do it to find the distance from a point to a plane (|ax0+by0+cz0+d|/sqrt(a^2+b^2+c^2)). The math behind it is pretty much the same, except you're projecting onto a normal instead of onto the line itself.
To anyone unsure about the above quote. Jeff is full of shit. Often he dances on the edge of wrong advice, today he has leaped over it.
You don't need to be a math whiz, but you damn sure need to be math inclined. At the very least you need logic. Any kind of graphics programming - math.
But if like Jeff your career consists of simplistic apps in VB, well then I still wouldn't call you a great software developer without math.
Don't aim to be at best average in your career, it makes for a shitty professional life, which is a big chunk of your whole life.
There's plenty of cutting-edge stuff to be done that doesn't require an intimate knowledge of mathematics. I would have to say that being good at arithmetic seems to be pretty important in programming, though.
Also arithmetic and even more so logic pretty much = applied math.
Pattern recognition, control systems, encryption, image and video compression (discrete cosine transforms in JPEG, discrete wavelet transforms in JPEG2000) any type of simulation (e.g. SPICE for electronic component simulation, RF simulation for electromagnetism, finite element models for mechanical systems) ...
Any type of planning system requires math (e.g. convex optimisation, network routing, etc...) - these types of things have huge applications in areas such as industrial engineering and network routing.
Basically all the interesting parts of programming require math.
All I'll say is, if you lack math background, then you may well end up doing things like making mincemeat of trying to explain NP-completeness. Just to pick a random example (heh).
(one of the Yegge quotes in the article)
I think this nails it.
It's a Blub thing. Jeff sees little use for Math because he does not know of any mathematical solutions for the problems he encounters. But...how can he think of a mathematical solution for a problem if he doesn't know very much Math?
Google, of course, relentlessly applies Math to everything they possibly can. I think that has worked out rather well for them. The flip side is that they might lose a good designer occasionally with good subjective judgment about hard to quantify things.
Of course, strictly speaking this doesn't mean that mathematics is necessary to do great work. Other qualities - say a good understanding of community (think Flickr), or psychology (Facebook), or design (37Signals) - can be equally useful. But, yeah, that post has "Blub" written all over it.
"Knowing some math can enable you to write some programs" - two separate activities, one benefiting the other. So, as a thought experiment, a non-mathematically inclined programmer with strong engineering / design aesthetics who implements an algorithm that has been prescribed by a mathematically inclined person may often produce a much better result than the mathematically inclined person would on their own.
Programming is related to and benefits from mathematics, but it is not only mathematics. It brings a whole range of skills into play.
When I was, oh, twenty or so, I used to be one of those systems programmers who thought that the fanciest data structure I'd ever need was a hash table. If you write real code, that other human beings use, one of those humans will eventually use it in a way you didn't anticipiate. And in that use, N will suddenly be large! The user will expect your code to work, and with reasonable resource consumption. "Mathematically uninclined" programmers' code will die with large N, and they're not "inclined" to fix it.
How can programmers not be mathematically inclined? Thinking logically about how to model and solve a system using abstract concepts. Computer science is a subset of applied mathematics.
I really should stop clicking on Coding Horror links on HN. Jeff is a very different style programmer than I am (and possibly a much better one). But his lack of understanding of the "other programming" is completely infuriating.
Which is often just as much or more in line with philosophical applications of logic than purely mathematical. As I noted in other comment, you could then argue that all philosophy and reasoning is basically conceptual mathematics, but people don't generally view philosophy this way despite the concept dating back 2500 years.
I don't understand the animosity you have for philosophical logic. I've always felt it was an interesting compliment to what I did in computer science and it made me appreciate discrete math concepts to a greater degree. The fundamentals building blocks are the same, just a different application.
In a similar way, it was hoped that a sufficient understanding of logic would enable one to reach philosophical conclusions more easily, with complete reliability. This sounds ridiculously naive to us, but we have the advantage of hindsight. At one time it was thought that with the investment of sufficient philosophical thought, logical rules of thought could be distilled and used to settle real problems. Unfortunately, it turns out that every application of logical rules requires so much examination of the validity of the application that little advantage is derived from logic beyond its ability to suggest and describe possible lines of thought, in the same way that UML and design patterns suggest and communicate but cannot replace the work of programming nor ensure the validity of resulting programs. Symbolic logic cannot be used to validate philosophical thought. To take an example of a deeply "logical" work, if you translated Spinoza's Ethics into symbolic logic, you would see nothing except some very trivial stuff and probably numerous errors. The profundity of Spinoza's work has little to do with logic in the mathematical sense. Once philosophers realized that, mathematical logic quickly became an ex-wife they had dinner with once a month. Never entirely forgotten, always thought of with affection, an important part of one's development, not without interest, but not looked to as a source of growth and vitality. You can certainly be a keen and insightful philosopher (though an ignorant one) without any understanding of mathematical logic, and a deep study of mathematical logic is rather useless for philosophy.
Now we muse about the "unreasonable effectiveness of mathematics in the natural sciences." At one time we hoped pure logic would help us decide questions about God and morality, and now we have learned to be surprised that it is useful for anything at all! Mathematical logic is an active field of mathematics, and philosophers have many problems to ponder, but there is no philosopher reading set theory abstracts looking for support in a dispute about aesthetics or ontology. Logic has become a branch of mathematics partly because it is necessary for mathematics and can be studied as mathematics, but also because no field outside of mathematics requires the solution of any complex problems in mathematical logic.
Even Godel's Incompleteness Theorem, while containing rich philosophical implications, did not actually apply to any philosophical ideas outside of math or logic because philosophers had long since given up using mathematical rules to "prove" or "derive" philosophical results. Philosophers were, as always, using language to express, justify, and criticize philosophical work. The use of logic as a tool for rigorously validating philosophical arguments, which was the original basis for the connection between philosophy and logic, is still a pipe dream.
I don't mean to denigrate either mathematics or anything outside mathematics by this. I have a math degree, but I'm the first person to admit that mathematical logic tells you nothing reliable about the relationship between "Every X is a Y, and Z is an X," and "Z is a Y." A proposition in symbolic logic can be derived mechanically according to its rules, but philosophy is uncertain and requires judgment. Mathematics is a useful tool for the natural sciences; in philosophy, mathematical logical is occasionally a stimulating subject for thought, but not a significant tool.
That's not strictly true. The Arab and Scholastic philosophers constructed a philosophical world-view, largely based on Aristotelian logic, which internally consistent fairly comprehensive. What resulted in its downfall, was not the failure of logic, but the desire for absolute truth. All forms of logic, whether mathematical or syllogistic, require argument from premises, which means that ultimately one must start with first premises that cannot be proved and must merely be agreed upon (making truth a matter of consensus.) Descartes tried to rectify this situation by assuming away all assumptions and proving first premises in a vacuum. He didn't get far (made too many logical fallacies) but he started a fad that overtook the philosophical realm and continues to this day.
My point being, that the problem wasn't the language (despite what the deconstructuralists might say,) which, if common and well defined presents no barrier, but changing ends in philosophical discourse.
> I was writing an Asteroids clone in Flash a few years back, I wrote my own insanely complicated functions for calculating directional velocity instead of using SIN and COS
fantastic, LOL! This supports Steve's position -- it illustrates that you'd need enough math background to at least know in what general direction you should be looking. And save yourself some coding time and pain to boot. Jeff Atwood on April 1, 2009 06:17 AM
Today, there are very few environments that has a higher data/cycles ratio than anyehere in the Apollo program in the '60, and most of the "hard" problems you'll run in to on a day to day basis have been commoditized - you'll be hard pressed to find a programming language where quicksort is even marginally hard to get to. Projects like My/PostgreSQL, Lucene and so on makes fulltext searches over very large corpuses of data crazy simple, even on consumer hardware. When I did a Scientific Computing project in college three years ago, we ran out of data long before our laptop fans came on.
Math matters in computer science, but tooling is moving the "competent programmer"-demography farther and farther away from the "computer science"-demography. And that is a good thing, just like the separation of programmer and user which happened in the early 80's (I guess)
Final thought: A former boss once told me, regarding education, that he knew plenty of very good, but no really great, programmers that didn't go to college for math and/or comp.sci.
A complete prescription for permanently disabling young minds — a proven cure for curiosity. What have they done to mathematics! There is such breathtaking depth and heartbreaking beauty in this ancient art form. How ironic that people dismiss mathematics as the antithesis of creativity. They are missing out on an art form older than any book, more profound than any poem, and more abstract than any abstract. And it is school that has done this! What a sad endless cycle of innocent teachers inflicting damage upon innocent students. We could all be having so much more fun. </quote> ([pdf] (25 pages) http://www.maa.org/devlin/LockhartsLament.pdf )
Here's the corresponing discussion on HN http://news.ycombinator.com/item?id=130499
"...to attack hard problems you need powerful solvents. I find math is a good source of metaphors good enough that it's worth studying just for that..."
I heard a scary story from a professor of economics who teaches business students. She said she talked about multiplying some value by 20 percent, and wrote on the blackboard "* .2," and then had students ask her why she wrote ".2" on the board when she had just said "20 percent." It probably avoids business logic mistakes to make the steps VERY explicit, so that the businessperson doesn't try to "correct" some error in the formula.
Why would a "business type" be looking at raw source code? (unless maybe said code is in COBOL)? I am not being sarcastic, but I've found even good business folks, being lost in (what to my eyes was) very clean code.
Another reason for the association of programming with math is that the two fields have an incredible intersection. As a math major, I took a lot of math courses that cross-listed with computer science or had a heavily computational component. Anyone who has taken numerical analysis or worked through the last third of the advanced algorithms book has seen the extent of this relationship.
There are huge classes of differential equations that can't be solved without programming. Same for optimization problems (the simplex method has to be one of the greatest intersections of math and programming in history). Simulation (and not just brain-dead random number slamming) has made it possible to solve probability problems that were unsolvable a couple of decades ago.
So while I tend to view math as domain knowledge for a programmer - ie., an area where you apply programming (like chemistry, real estate, acounting...), the relationship seems deeper and more natural.
more specifically on relations, though most database schema in the wild are not really relational. I've personally found knowing relational algebra a great help in designing db s, formulating queries and so on.
Yet, somehow he is making a living off barely visible ads and no real job that he discusses; surely Stackoverflow is not making that much money.
Here: http://www.codinghorror.com/blog/archives/001216.html
surely Stackoverflow is not making that much money.
But StackOverflow delivers, more so than most YC startups.
I do, however, agree with the point that in the general case, programmers tend to be able to learn quickly, and learn the types of things to help them with their current problem. But if you don't have a grounding to even know where to begin looking for answers, you have a bigger problem.
Certainly all programmers do not need heavy math skills. But it certainly never hurts. All things being equal, I know which one I would rather go with.
The problem is that what Dijkstra means by "competent programmer" is not what Jeff means. It's not just that they are talking about different levels of competence – they aren't even talking about the same discipline.
Dijkstra may have meant something like "doing meaningful work in computer science" or "solving algorithmic challenges". Jeff Atwood seems to mean something like "gluing libraries together to accomplish a business objective".
At the beginning of Jeff's post, it almost sounds like he has something interesting to say about the Dijkstra quote, but that's just because he confusingly uses the same word to mean something almost completely unrelated. As he says "the vast bulk of code that I've seen consists mostly of the 'balancing your checkbook' sort of math." I don't think that's quite what Dijkstra had in mind. Likewise, I suspect finding new algorithmic approaches to tough computational problems is not high among Atwood's interests.
Granted, this is coming from someone who enjoys math (the parts I understand anyway) and programming. I'd be curious to hear from someone who enjoys programming.
Basic algebra, linear algebra, abstract algebra, discrete math... I apply concepts from these areas constantly.
So any competent programmer necessarily has some kind of mathematical inclination.
It's boot camp for the brain.
If you don't know any math you could waste your time rederiving concepts from first principles when you could just have learned the established theory.
It amounts to arguing that arithmetic is as relevant to programming as discrete mathematics are.