Logical bugs are very common in code and are often very difficult to find and fix. In this column, we’ll look at an example of a real-world logical bug, and explore how intuitive thinking might have caused it.
During lunch, one of my colleagues asked me this question: “A baseball bat and ball together cost one dollar and 10 cents. The bat costs one dollar more than the ball. How much does the ball cost?”
I immediately replied: “It’s an easy question. 10 cents.”
With a smile, my colleague gave me the background of the question. Daniel Kahneman, in his Nobel Lecture (for the Prize in 2002), gave this as an example while talking about the differences between intuition and reasoning. Almost everyone tends to answer as I did. Around 50 per cent of the students in the University of Princeton and 56 per cent of those in the University of Michigan gave this (wrong) answer! [Read the paper, Maps of Bounded Rationality: A Perspective on Intuitive Judgement and Choice by Daniel Kahneman (PDF).]
Why do we make this mistake? Because the value $1.10 separates easily into $1 and 10 cents! So, intuitively, we answer: “10 cents.” Instead, we can proceed logically. Say the cost of the ball is x, and the cost of the bat is y. x + y = 110. Now, y = x + 100. So, we’ll arrive at x = 5 cents, which is the correct answer.
This example explains why logical bugs are very common in code — programming requires reasoning, but we think intuitively! Here is an example. The following code segment is meant to increment the variable year
, based on the value of another variable, days
. Can you tell what is wrong with this code?
// assume days and year are ints // year starts from 1980 while (days > 365) { if (is_leap_year(year)) { if (days > 366) { days -= 366; ++year; } } else { days -= 365; ++year; } }
This code might never terminate if it is a leap year, and the value of days
is exactly 366; the else
part is missing, so days
will never get decremented in that case! This code segment is loosely based on the bug that caused Microsoft’s Zune-30 media players to freeze on Dec 31, 2008, which was the last day of a leap year.
The initial workaround suggested was to drain the battery and recharge it on the afternoon of the following day, so that the days
value would have changed!
Wrong termination conditions in loops (and recursion) are some of the most common logical mistakes. Let us look at another example. Quickly: how many fence posts will you need if you’re building a 100 feet fence with each fence post 10 feet apart?
It is 11, and not 10! From this puzzle, “off-by-one” errors in programming have acquired the name “fence-post errors”. This logic bug is caused because of intuitive thinking.
Don’t get me wrong — I am not saying that you don’t require intuitive thinking for programming. My point is that intuitive and impulsive thinking often leads to bugs in code!
Feature image courtesy: JackAZ Photography. Reused under the terms of CC-BY-NC-SA 2.0 License.