20

It seems that off-by-one errors are one of the most (if not the most) common programming errors (see https://softwareengineering.stackexchange.com/questions/109/what-are-common-mistakes-in-coding, and conventional wisdom).

What is the reason these are so common, is it something to do with how the human brain works?
What can we do to prevent falling prey to the off by one errors?

  • 8
    Are they common? I'm producing my fair share of bugs, but off-by-one errors are very rarely among them. Perhaps because I mostly use Python, i.e. use iterators instead of juggling with indices? (And: What does that tell us? ;) ) – user7043 Feb 2 '11 at 18:16
  • The less you have to think about, the more productive you are? – Malfist Feb 2 '11 at 18:20
  • @delnan: I agree. Off-by-one errors are usually the first to be caught when I'm coding (before I even move to an official "testing phase"). – FrustratedWithFormsDesigner Feb 2 '11 at 18:24
  • 7
    I almost answered the previous question by mistake... – DevSolo Feb 2 '11 at 19:07
  • > What can we do to prevent falling prey to the off by one errors? Use an iterator. – Jim G. Feb 3 '11 at 0:14
18

It sort of is something to do with how the human brain works. We're wired to be "good enough" for tasks that don't usually require engineering-grade precision. There's a reason why the cases we have the most trouble dealing with are called "edge" cases.

Probably the best way to avoid off-by-one errors is encapsulation. For example, instead of using a for loop that iterates a collection by index (from 0 to count - 1), use a for-each style loop with all the logic of where to stop built into the enumerator. That way you only have to get the bounds right once, when writing the enumerator, instead of every time you loop over the collection.

  • 6
    +1 for encapsulation. The worst off-by-one bugs I have ever seen are when part of the program is 1-based and part is 0-based, and every single function it is used, you have to remember which one it was and whether you have to do the conversion or not and which direction to go. A couple months ago I had to track down a difficult off-by-2 error because poor encapsulation meant someone made off-by-1 errors in two separate compounding places. There were conversions all over the place that were impossible to follow and I was able to get it down to one conversion in one method. – Karl Bielefeldt Feb 2 '11 at 19:26
  • 2
    I'd love to learn more about the science of this if anyone has more info. I also think this is why programatic styling, like CSS, is so frustrating where everything is edges... – Company Laser Aug 12 '16 at 1:48
7

There is something special about how brain handles borders and edges.

While it's easier for the brain to think in terms of ranges and spaces, focusing on an edge seems to require somewhat more of attention. Here is how it happens, momentary loss of attention or insufficient concentration and you missed the border.

Another slight addition to the problem is that different programming environments have different indexation systems starting at either 0 or 1 which might add confusion to the people actively exposed to the both types of environments.

4

I believe it is due to context switching. In our day to day lives we tend to use 1-based indexes. Because of this our brain is unable to burn the correct behavior into long term memory.

  • 2
    And then there's the fun of switching between programming langauges which DO index starting at 1 (such as PL/SQL). – FrustratedWithFormsDesigner Feb 2 '11 at 18:25
  • 3
    +1 for that. 1-indexed numbering answers the question "how many are there?", which maps neatly to most real world tasks. 0-indexed is about "what position is each item in?", which is of less use in meatspace. – Dan Ray Feb 2 '11 at 18:34
-4

I believe that there is a thing with subtraction between integers if they are representing indexes or ranges. The solution to this is to separate the range and index concepts.

protected by gnat Dec 13 '16 at 12:54

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.