The Dirty Little Secrets of Real-World Math
July 13th, 2008In my “Real-World Math” article that posted to StickyMinds on July 14, I didn’t have room to explore some of the dark secrets underlying the article. First, discussing mathematical topics with my peers and editors often gave me feelings of inadequacy. I mentioned probability theory, and one person starts to talk about how he regularly uses combinatorics to analyze test inputs. The terms he used sounded vaguely familiar, but it would have taken a lot of study for me to really grok what he was doing. When he related a story about bivariate data, I knew I was really on shaky ground. When I posed a question on the Toolsmith Guild about using logarithms to speed up the search for the boundary between a pass and a failure in a test, people started talking about root finding algorithms, slopes, and convergence, and I feared that I didn’t have the foundation for having an intelligent conversation.
Still, I pressed on, determined to write about only things that I understand reasonably well. The finished result, though, doesn’t show how the sausage was made.
It’s all story problems
Remember how annoying it was to do “story problems” in math class, where you weren’t spoon-fed the numbers you needed to plug in to a formula? Well, bad news - most real-world math challenges are story problems, and the relatively simple algebra example in my Real World Math article was one of them. I didn’t describe the difficulty I had in setting up the problem, starting with defining the variables. Is “D” the number of developers before or after some of them become testers? Do I need one variable for before and another for after? “T” is the number of testers, which is 0 right now, but may be non-zero later. I had a few false starts before I decided that it would work best for all variables to reflect the state of things after some of the developers had become testers.
I first set up the equations like this:
T = D / 4
T + D = 200
And solved for D like this:
T + D = 200
D / 4 + D = 200
D(1/4 + 1) = 200
D = 200 / 1.25
D = 160
This is somewhat more complex than the final version I settled on for the article, though it’s just as valid. It seemed a bit more straightforward to represent the first formula as “D = T * 4″, and I solved for T in the calculations instead. I was able to avoid the ugly “1.25″ in the new version.
I imagine that textbook authors go through this same process, and while it’s nice that the published version looks elegant and easy to understand, I think people can get very frustrated when their own calculations look uglier and more belabored than the polished examples in the books. Real-world math is uglier than the textbooks, and my own article, imply that it is.
Bad test code
While writing about the modulo function, I found a bug in my test code. I was keeping a count of the total number of virtual users that had been started, like this:
wlGlobals.userCount++
wlLocals.userNum = wlGlobals.userCount % wlGlobals.totalUsers
This code has a race condition, because it’s multi-threaded. Thread 1 could execute “wlGlobals.userCount++”, then get interrupted so thread 2 can run, which then also executes “wlGlobals.userCount++”, and when we eventually switch back to thread 1, it ends up using the same userCount value as thread 2. I explored ways to do locking to try to make the code thread-safe, but then found the built-in “ClientNum” variable, so I didn’t need to keep my own count after all.
I often find bugs in my test code when trying to explain it to other people. I should do that more often.
How does a logarithm work?
In the article, I write about my disk stress test that chooses a chunk size using this formula: “int exp(rand(log($filesize)))”. I admitted that I still don’t feel like I understand logarithms well enough to understand why this works, so I ran some experiments that showed that it does accomplish what I wanted. I knew I wanted a formula that used a logarithm function, and I used a good deal of intuition to cobble together the formula. Maybe my subconscious understands it, but I still have a nagging sense that I don’t understand what’s going on. I understand the basic concept. I can even draw the rough shape of it on a graph. But I still don’t feel I understand why generating a random number after taking the logarithm then immediately reversing the logarithm actually works. Maybe this is why we’re supposed to show our work when we do our math homework. In this case guessed the answer without doing the work at all.
While trying to study logarithms with Google’s help, I saw that the derivative of the logarithm function is the inverse function (1/x), and a graph of the inverse function looks just like I want the distribution of my test values to be. But I wasn’t about to try to bring calculus into the conversation. That would just ramp up my feelings of inadequacy even further.
I even resorted to slide rules. Having heard that slide rules use a logarithmic scale, I asked my father-in-law to get out his slide rule and show me how it works. He gingerly handed me his prized slide rule, which his own father had used. And I dropped it. Shattered the cursor beyond repair. Anyway, long story short, with eBay’s help I found a replacement cursor, and several slide rules I could keep for myself. But I still haven’t gotten that lesson, and the online tutorials I found have shown me that these things aren’t as simple as I had hoped. So while previous generations may have a deep understanding of what makes a logarithm tick, they have years of experience that my digital calculators have deprived me of.
Oh, one more thing. The first version of the disk stress algorithm that I used actually first calculated the position of the file to start writing from using a random number on a linear scale, then used the logarithmic scale to calculate the chunk size. The range of the chunk size in that case was from 1 to the end of the file from that starting position, making the average chunk size perhaps half as big as it is with the formula I described in the article. I decided it would be more straightforward to first calculate the chunk size, up to the full length of the file, then calculate a random starting position using a range of possible positions where the chunk wouldn’t run off the end of the fixed file size. So again, after having to explain my code, I found a way to improve it.
Popularizing math
I think we need more authors to help popularize mathematical concepts. Like Ivars Peterson did in Islands of Truth: A Mathematical Mystery Cruise. But Peterson talks about four dimensional geometry and fractals, not more practical applications that people are likely to use regularly. I even had a hard time getting into George Polya’s classic book How to Solve It, often on recommended reading lists for computer professionals.
Is math just inherently too difficult to write about in a way that people understand? For my StickyMinds article, we even had to seek outside help to proofread the math. But I don’t think it’s impossible to make math approachable. What do you think?