24

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?

Malfist
  • 3,641
  • 5
  • 29
  • 40
  • 9
    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? ;) ) –  Feb 02 '11 at 18:16
  • 1
    The less you have to think about, the more productive you are? – Malfist Feb 02 '11 at 18:20
  • 1
    @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 02 '11 at 18:24
  • 8
    I almost answered the previous question by mistake... – DevSolo Feb 02 '11 at 19:07
  • 1
    @delnan, iterators is perhaps the most robust way to avoid off-by-one errors –  Jul 24 '11 at 20:46
  • 1
    > What can we do to prevent falling prey to the off by one errors? Use an [iterator](http://en.wikipedia.org/wiki/Iterator). – Jim G. Feb 03 '11 at 00:14

3 Answers3

22

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.

Mason Wheeler
  • 82,151
  • 24
  • 234
  • 309
  • 7
    +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 02 '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 01: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.

ChaosPandion
  • 6,305
  • 2
  • 33
  • 33
  • 2
    And then there's the fun of switching between programming langauges which DO index starting at 1 (such as PL/SQL). – FrustratedWithFormsDesigner Feb 02 '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 02 '11 at 18:34