[HN Gopher] Why do arrays start at 0? ___________________________________________________________________ Why do arrays start at 0? Author : snikolaev Score : 248 points Date : 2022-08-24 16:25 UTC (6 hours ago) (HTM) web link (buttondown.email) (TXT) w3m dump (buttondown.email) | lowbloodsugar wrote: | The argument that "BCPL doesn't have pointers, so it's not about | pointers" fails immediately because every language has pointers, | but some of them don't expose them to the developer. | walnutclosefarm wrote: | There were a number of systems oriented languages that, while | algol-like in syntax, used zero-based array indexing, predating | C. BCPL was intended to be a generic systems oriented language, | but Burroughs had ESPOL for their mainframe architecture, and HP | wrote their operating systems and compilers in SPL, which was | specific to their stack-oriented HP3000 architecture. All these | used zero-based indexing, because for low-level, memory conscious | manipulations, it's much more natural than one-based. But nothing | is universal, and IBM's systems oriented languages (BPL, PL/S, | and PLS/II) were more an evolution of IBM assembler and then | Wirth and PASCAL, and used one-based array indexing. | | Personally, I've always found zero-based more intuitive and | satisfying, absent arbitrary indexing (in which case I'd chose | zero-based for most purposes where there wasn't a compelling | solution based reason to use a different index base). But then | spent years writing SPL ... I | unixbane wrote: | On a cursory look, I'd say _one_ based is more intuitive, for | the sole fact that the a[len(a)] is the last element. Actually | I remember there was a small time when I started programming in | assembly it took me a while to get used to reasoning about the | end of the array. | [deleted] | v-yadli wrote: | I'm fine with 0-based, 1-based or anything-based arrays (I recall | it being convenient solving 8queen with pascal), but for Rage- | Over-A-Lost-Penny sake, music note intervals are always beyond my | understanding. | | Same pitched notes are called "interval 1" and there goes thirds, | fifths, sevenths... All off-by-one in my base-offset-addressing | mind... And then major vs. minor which creates all kinds of | "aliased addresses"... | | I'd really love a BASE-12 floating number representation. Like | 4.00 for the middle C; Chords can be then represented by a tuple | of such numbers -- major = [+0.04, +0.07] (some sequencers | already do something like that and I'm far better at reading that | kind of sequencer data than a sheet) | gnulinux wrote: | You do understand that besides thirds, fifths and sevenths, | there really are seconds, fourths, sixths, ninths (same as | second), elevenths (same as fourth) etc... as well, right? | There even are intervals that are not named after a number e.g. | the "tritone". The reason the 2nd and the 3rd note in a chord | are called third and fifth is because usually chords are made | with these intervals instead of dissonant intervals like | seconds or fourths. It seems pretty clear you'd already know | these things, so can you explain what's your issue with music | note intervals? | v-yadli wrote: | It's that off-by-one nature of intervals that always bumps | me. The difference between note a and b is (a-b+1). Calling | an octave "an octave" feels to me like calling a numeric | system with digits 0x0-0xf as "base 17" | ur-whale wrote: | And then, there's the imperial system. | Taywee wrote: | I've spent so long working with both 0-indexed and 1-indexed (I | work with Lua a LOT at work) that it makes almost no difference | to me, and I can switch between the two with usually no hiccups. | | Either one is something you get used to with practice. I do | prefer 0-based, but 1-based isn't as big of a deal as many people | treat it in the vast majority of situations, and almost every | situation where you'd be using something like Lua in the first | place. | kybernetyk wrote: | Because an array is just syntactic sugar for pointer arithmetic | ... at least in C :) | ncmncm wrote: | The crucial fact is that if your language supports 0-indexing, | you can do that if you like. OR, you can pretend it has | 1-indexing, and do that instead. | | If your language doesn't support zero-indexing, then you are | stuck with 1-indexing, and that's that. | | So, zero-indexing is the natural thing to put in a language, as | it accommodates everybody. | soheil wrote: | Qbasic uses 1 and that's what I always loved about it. | Coincidentally it was the same language I learned programming | with at age 12. | daneelsan wrote: | In Mathematica/Wolfram Languege, the part 0 of an expression is | reserved for the head of the expression: f[x, y, z][[0]] == f. Or | g[f][x, y][[0, 1]] == f. | [deleted] | [deleted] | charlieyu1 wrote: | A problem with 0-based arrays is that 0 is the only index with a | Falsely Boolean value. | onox wrote: | Arrays in Ada start at the index based on the index type of the | array. You can even use an enumeration type as the index: | type Day is (Monday, Tuesday, Wednesday, Thursday, Friday, | Saturday, Sunday); type Hours is array (Day range <>) of | Natural; V : Hours (Monday .. Friday); | | Which index type you should use depends on the problem that | you're trying to model. You can find out the lower/higher end of | a type/variable with the 'First and 'Last attributes. | | IIRC there's an RFC though to force the lower end of the index to | a certain value like 1 or any other number/enum. | copperx wrote: | I always wonder why such fundamental features were not adopted | by all languages. | shanewilhelm wrote: | I found it interesting that the author phrased their critique so | definitely, i.e. "it's NOT this and NOT that", yet concluded the | article by saying their whole argument was speculative. That | said, I do agree with their premise that it's going to be pretty | tough to get a definitive answer as to why 0-indexing won out. | And their criticism of others being so ready to declare results | is apt, if not a little ironic in this case :) | briantakita wrote: | > yet concluded the article by saying their whole argument was | speculative | | It's possible to have a speculative argument and also refute | other arguments that claim certainty. Pointing out another | answer as being wrong does not mean one needs to know the | correct answer or claim to have a precise answer. | asveikau wrote: | There is definitely a bunch of math that works out better in 0 | based indices. I saw this a lot when I was working on filesystem | focused stuff. | | I feel like I've also seen algorithms that work out better with 1 | based indices, but not as many. | thwarted wrote: | If your arrays start at 0, you have offsets. | | If your arrays start at 1, you have indexes. | | "0-indexed" shouldn't be a thing. I like the screenshot quote | that refers to this as either "1-origin" or "0-origin". | mmaunder wrote: | Because if you iterate backwards through an array your | terminating condition can be when your iterator evaluates to | false in loosely typed languages. /jk | dang wrote: | The article this one points to has had a few threads: | | _The origin of zero-based array indexing_ - | https://news.ycombinator.com/item?id=6879478 - Dec 2013 (107 | comments) | | _Zero-based arrays and the mythology of programming_ - | https://news.ycombinator.com/item?id=6708409 - Nov 2013 (1 | comment) | | _Citation Needed_ - https://news.ycombinator.com/item?id=6595521 | - Oct 2013 (2 comments) | | Threads about the EWD mentioned by jaapsen01: | | _Why numbering should start at zero (1982)_ - | https://news.ycombinator.com/item?id=22162705 - Jan 2020 (220 | comments) | | _Dijkstra 's argument on why numbering should start at zero | [pdf]_ - https://news.ycombinator.com/item?id=17850441 - Aug 2018 | (1 comment) | | _Why numbering should start at zero (1982)_ - | https://news.ycombinator.com/item?id=17765034 - Aug 2018 (63 | comments) | | _Why numbering should start at zero (1982)_ - | https://news.ycombinator.com/item?id=13186225 - Dec 2016 (216 | comments) | | _Why numbering should start at zero (1982)_ - | https://news.ycombinator.com/item?id=9761355 - June 2015 (47 | comments) | | _Dijkstra: Why numbering should start at zero_ - | https://news.ycombinator.com/item?id=777580 - Aug 2009 (71 | comments) | | Also these. Others? I'm a little surprised there aren't more. | | _Why do we count starting from zero?_ - | https://news.ycombinator.com/item?id=17923391 - Sept 2018 (1 | comment) | | _Why C Arrays Start at Zero: I Don 't Know_ - | https://news.ycombinator.com/item?id=11228267 - March 2016 (3 | comments) | | _Why C Arrays Start at Zero: I Don 't Know_ - | https://news.ycombinator.com/item?id=11114704 - Feb 2016 (2 | comments) | cannam wrote: | Perhaps also worth adding that the linked article (the one | titled "Citation Needed") itself originally had hundreds of | comments beneath it, many quite argumentative, which seem to be | now missing - I guess lost in a site update. It was a very | contentious article. | | I'm sympathetic to its author's approach - we talk about | indexing and it's a strangely fascinating topic but the history | of it hasn't been all that well dug out. We do indeed tend to | respond to articles like this by going "well obviously | [x]-based is good because" - you can see that at work in this | discussion here - but those are not necessarily the true | historical reasons. But I think the author made a leap too far, | the article was a bit too brittle, and it landed in a slightly | too argumentative spot. | Symmetry wrote: | For me, far more significant than anything else here is having to | convert array indices into human readable text describing | objects. And the objects are named by mechanical engineers who | don't use 0 based indexing. So my code is full of | print("Finger {}'s motor has overheated".format(i+1)) | zzo38computer wrote: | I think that zero indexed is generally better, including that it | involves adding the index number to the base address, and other | properties that can be helpful. | | However, it can also be useful for many purposes to allow | arbitrary ranges, so a programming language probably should allow | that; if the index of the first element is not zero, then the | base address will not be the address of the first element (if the | first element index is positive, then the base address may | actually point into a different array, or a different variable). | Then, if you have the base address and add the index, you will | have the proper address of that element, whether or not the first | index number is zero. | | Zero is not always the most useful starting index; sometimes | other numbers (which may be positive or negative) are useful. | But, I think in general, zero is better. | jaapsen01 wrote: | Edsger Dijkstra wrote an interesting article titled 'why | numbering should start at 0'. Perhaps not answering the question | directly but an interesting read nonetheless. | | https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E... | oboes wrote: | Interestingly, that Dijkstra article was originally | published/circulated in handwritten form. It helps showcase the | author's handwriting skills. | | https://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF | Koshkin wrote: | The handwriting skills were common back in the day... By the | way, are you sure that it was Dijkstra himself who hand | _printed_ these texts (rather than have, say, his secretary | do that)? Because this is not exactly the (beautiful) | handwriting as it was taught back then. | Jtsummers wrote: | He handwrote them, and occasionally typed them (especially | early on, I gave up trying to find the transition point). | It was something he was known for. If you read the EWD's | over the years you'll see the same (or _very_ similar) | handwriting throughout, which would not be the case if he | had a secretary writing them for him (who wouldn 't have | been the same person as he moved between countries). | | https://en.wikipedia.org/wiki/Edsger_W._Dijkstra#EWD_manusc | r... | | https://www.cs.utexas.edu/~EWD/ - Pick random ones from | different decades and you'll see very similar handwriting. | | (Didn't read these, picked two at random): | | 2001 - https://www.cs.utexas.edu/~EWD/ewd13xx/EWD1307.PDF | | 1984 - https://www.cs.utexas.edu/~EWD/ewd09xx/EWD901.PDF | pavon wrote: | I've never understood the first half of Dijkstra's argument. | Unless we are programming a theoretical Turing machine, there | will also be a maximum number that can be represented, so the | argument about using inclusive bounds for the lower end also | applies to the the upper end. So you can't represent all | numbers with a single range style. You either end up excluding | the smallest number, the largest number, or the empty set. Or | you need special notation to handle one of those three cases. | | I suppose the 0,1,infinity principle argues that including the | empty set and smallest number is more important that including | the largest number, so that notation should be preferred by | default. And when writing using A<=i<B it is clear enough, but | once you remove those symbols and start using them in indexing | or function call syntax, like [A:B] or range(A,B), the | inconsistency of bounds really breaks my brain, and having to | pass a number larger than the largest array index as an upper | index range bound gives me nervous ticks. I'd rather use | inclusive bounds everywhere and have special syntax for empty | set. | zeroonetwothree wrote: | Sure but it's much more common for a range to include 0 than | INT_MAX | [deleted] | gnufx wrote: | As the article implies, Dijkstra was specifically wrong about | FORTRAN, as defined at the time -- the '77 standard, when it | was still only conscionable to SHOUT 6 alphamerics. | | "... you probably know that arrogance in computer science is | measured in nano-Dijkstras." -- Alan Kay | tda wrote: | "This quote keeps on showing up out of context." -- Alan Kay | https://news.ycombinator.com/item?id=11799963 | jefftk wrote: | My favorite example of this confusion is JS and (original) Java | dates: > new Date() Wed Aug 24 2022 ... | > new Date().getFullYear() 2022 > new | Date().getMonth() 7 > new Date().getDate() | 24 | | So 2022-08-24 comes out as (2022, 7, 24). One-based indexing for | the year and day, zero-based indexing for the month. | iainmerrick wrote: | That comes from C's standard library (and presumably from | somewhere else before that). Classic bad design, took a very | long time for people to figure out it was unhelpful and | dangerous. | jefftk wrote: | https://linux.die.net/man/3/localtime: | tm_mday: The day of the month, in the range 1 to 31. | tm_mon: The number of months since January, in the range 0 | to 11. | | I wonder where C got it? It goes back to at least 1973's V4: | https://github.com/dspinellis/unix-history- | repo/commit/92779... | Jtsummers wrote: | https://minnie.tuhs.org/cgi- | bin/utree.pl?file=V6/usr/source/... | | Convenience. Look at how the days in the months are stored | and accessed. Using 1-based months would introduce an extra | calculation (-1) on all searches or an unused value in the | 0-index. Also look at how printing is handled for weekday | and month names. They, again, take advantage of 0-based | indexing. | | Day and year are already represented as numbers, so it's | natural to keep them as the "correct" (conventional) number | as used by most people. Since the months aren't being | stored as strings but as an index, this saves them from | having useless data (entries in 0) or doing an extra | calculation. | jefftk wrote: | Subtracting 1 from the user provided index isn't that | expensive. | | Or, if you're willing to give up three bytes, index into | "ErrSunMonTueWedThuFriSat". | | Or, and this is mildly insane but perhaps in keeping with | early C, have your pointer be three bytes before the | beginning of "SunMonTueWedThuFriSat" and use one-based | indexing. | Jtsummers wrote: | It all boils down to the fact that C's memory model is | meant to map closely to the physical memory model, and | the C and Unix developers preferred simplicity of | implementation over simplicity of interface. Leaky | abstractions (like that the weekday or months start at 0 | so that they can reference into arrays of names) are fine | given that prioritization. Not everyone shares that | preference. | [deleted] | AndrewOMartin wrote: | "Should array indices start at 0 or 1? My compromise of 0.5 was | rejected without, I thought, proper consideration." -- Stan | Kelly-Bootle | pavon wrote: | This comes up when giving fractional coordinates into a grid. | Is (1,1) the upper-left corner of the upper-left grid box, the | center, or the lower-right (or the center of the next grid | box)? Alternately, is the upper-left corner of the upper-left | grid box (-0.5, -0.5), (0.0, 0.0), (0.5, 0.5), or (1.0, 1.0). | I've seen all four conventions used in different places, | depending on whether the grid boxes themselves are numbered | starting at 0 or 1, and when extended to fractional if it makes | more sense to have the corner or the center of the grid box | take the value of the box itself. | bartwe wrote: | Which is how we got the dx9 half pixel offset in fragment | shaders. luckily not replicated in newer revisions. | Stratoscope wrote: | A related question: why is a rectangle containing a single pixel | defined as (x,y):(x+1,y+1) instead of (x,y):(x,y)? | | Here's a discussion from some years ago that starts with some of | Guido's thoughts on array indexing and moves on to the QuickDraw | coordinate plane and points and rectangles, including how grid | lines and points are infinitely thin/small, but pixels occupy the | space _between the grid lines_. | | https://news.ycombinator.com/item?id=6602497 | thomasahle wrote: | Discussion form 2013: | https://news.ycombinator.com/item?id=6601515 | WaitWaitWha wrote: | I started programming in assembly, then Fortran, Algol, COBOL, | etc. | | 0 based index makes sense to me. The memory location is offset 0 | bytes from where the first data byte is stored (without getting | into endianism). | kgwxd wrote: | If everyone just called it offset instead of index there'd be no | confusion. | Schroedingersat wrote: | The correct starting ordinal is 0. A list with a 0th element has | cardinality 1. This is a concept that exists in many places in | english, where the naturality of starting with the zeroth element | trumps inertia but english is wildly inconsistent so it has both. | | Constructing the naturals without including 0 and starting with | it is incredibly awkward. Addition doesn't even have an identity. | | Look at a clock, is 1 at the top, or is it the next one after the | top. | | Look at a ruler. Does it start at 1? | | Do you want to have to shuffle everything around when you go from | whole numbers to halves? Do you start at 0.5 or 0? Depends if it | is "halves" or the real number 0.5 | | This is a recipe for pain and off by ones any time you're dealing | with time steps (which is why it's so stupid that matlab and | fortran are 1 indexed by default, if anything there's a better | argument for C to be 1 indexed than scientific languages). | | Now index and compose a bunch of ranges. A half open range of two | elements is incredibly stupid 1 <= i < 3. | | So closed ranges go with 1 indexing. Composing and splitting them | is incredibly awkward [a,c] is split into [a,b], [b+1, c] ... | that's kind of okay, but not unique as you could use [a,b-1], | [b,c]. Now do [d,e], [e,f] compose at a glance? | | Half open ranges go with zero indexing and they just work. | JKCalhoun wrote: | > The usual arguments involving pointer arithmetic | | Yeah, I think this exactly why it is zero based. The index became | a simple multiplier for sizeof(int). | hougaard wrote: | An assembler spillover into C. | JKCalhoun wrote: | Was C ever much more than a veneer on top of assembler? | | Don't get me wrong, it's why I like C. | adwn wrote: | > _Was C ever much more than a veneer on top of assembler?_ | | Maybe in the very early days, but that necessarily had to | end as soon as compilers started doing non-trivial | optimizations. Today, C is _very far_ from being "portable | assembly". | JustSomeNobody wrote: | I liked how in Pascal, one had a lot more flexibility here. | | Something like the following IIRC: Type IntArray = Array | [-10...10] of Integer; | drfuchs wrote: | Easy: I have an array with 256 elements. And I want to store the | indexes of various elements of the array off in another data | structure. So many of them, in fact, that it's important that the | index values each fit into a byte. So, I want the index values to | be 0..255, and not 1..256, since 256 doesn't fit into a byte. | _gabe_ wrote: | You can still fit that information into one byte and convert it | at compile time or runtime :) | | In a minecraft clone I made, each chunk consists of 16 | subchunks so that I only need 12 bits to represent the block | position in the shader. Technically, the block position ranges | from INT32_MIN -> INT32_MAX, but since each subchunk only | consists of 16x16x16 blocks I can get away with storing the | position in 12 bits and then passing in the subchunk's world | position once as a uniform. | Guest42 wrote: | I'd claim intuitively that having all bits 0 is a proper starting | point and more efficient if there were any constraints on | address, which was likely the case historically. | | I'm happy to hear any dissenting opinions if this is inaccurate. | dboreham wrote: | Unusually for me, I read TFA first. Immediately thought "this is | all wrong", then realized 400 commenters had posted the same | thing already. | | I have Martin Richards book on my shelf, and for a while shared | an office with his coworker. I'm also one of the few folks here | who has coded in BCPL. | | Ok, so that said, this article is obvious nonsense. Zero indexing | comes from the CPU itself. It's how you generate an indirect | address by adding the offset. Many CPUs have this in hardware. | They don't support non-zero offsets. The reason some languages | have zero-based indexes is that their developers had the mind set | of doing the same thing you do when writing machine code. They | probably also wanted to directly interface between their language | and libraries written in assembler (and the kernel was typically | written in assembler too). Also they wanted to be efficient. Any | offset other than zero is not efficient because you can't use the | hardware addressing modes. | | So then why do some languages _not_ have zero based indices? The | obvious answer it that Mathematics by convention always used 1 as | the base (or some arbitrary value). Many languages were conceived | by mathematicians or people with a strong mathematical | background. | patatino wrote: | My 4 year old starts at 0 when asked to count, so proud! Never | said a thing about starting at 0. | thetwentyone wrote: | They point at 3 apples and goes "0,1,2" naturally? | jcelerier wrote: | Look at your 4 year old's ruler. What's the first number on it? | zaroth wrote: | Simple: Because you add zero to the memory address of an array to | access the first element. | | The array indexer was syntactic sugar for pointer arithmetic. | avisser wrote: | Looking at my own coding experience, I certainly favor 0 over 1. | When I examine why, I can't help but see my aversion to & | distaste of Visual Basic as a driver. | | VB is the only 1-indexed language I have used. VB is bad. | Therefore 1-indexed languages must be bad. | OJFord wrote: | Why do tape measures start at 0? | hougaard wrote: | It really comes down to a choice between a machine-focused (0) or | human-focused (1) approach. | | The 0 makes a lot of sense in a C pointer world where memcpy and | other alike functions can be written very thight. | | The 1 makes a lot of sense in a human world, when we count, we | start at 1, we talk about the "1st", counting on finger starts | with 1, etc. | | I once were at a Lua (1 indexed language) conference where this | was discussed, and Luis started explaining why Lua was 1-index | with this sentence: "The 1st argument ...." :) | co_dh wrote: | Human makes a lot of inconsistent thing: We usually think the | 1st floor, and the basement as 1st underground floor ( -1), but | the floor jumps from 1 to -1! | | Also, the time jump from 11AM to 12PM to 1PM! So I think more | human friendly sometimes means more confusing. | copperx wrote: | It's like English pronunciation, there's little logic. I gave | up finding logic in these things at an early age, and | resorted to memorizing everything instead. | luispauloml wrote: | That's true. But as for floor numbering, specifically, it | depends on the country: some places have a "ground floor" | between the 1st underground floor and the 1st "above ground" | floor. | BorisTheBrave wrote: | In Europe, the floor level with the ground is called "ground" | or "0". | bregma wrote: | Ah, yes. Cardinal numbers and ordinal numbers both end in the | word "numbers" so they're the same thing. No need to | distinguish between having three apples and having the third | apple. | Old_Thrashbarg wrote: | If you ask most people to just label their apples, they'd | call the first one "1", and so on. Very few people would say, | "please pass me apple #0". | goatlover wrote: | And if someone did say that to me, I would pass them no | apple, since that's how we use everyday language. And if I | knew they were a programmer, I'd first ask them in which | programming language they'd wish me to pass the apple. | Old_Thrashbarg wrote: | I believe there's a powerful status quo bias. | | Doing the reversal test, if programming languages had all been | 1-indexed, then I doubt we'd hear much from people, in 2022, | saying "I think the first element should be 0, and the second | 1". | croes wrote: | If you think of the index as an offset you would start with 0. | | BTW on which level is the 1st floor? | hougaard wrote: | That depends on your language and culture, "floor" is not | easily translated, some languages have a word describing all | the layers added to the base layer, so "1. sal" (Danish as an | example) actually means "the first layer added on top of the | base house". | | Again, this is more a spoken language/culture thing, and this | goes back to what premises we use to communicate with the | machines, ours or the machines... | t_mann wrote: | > BTW on which level is the 1st floor? | | in Europe or in the US? | ethbr0 wrote: | Does Europe has a zero floor? Please tell me Europe zero- | indexes their stories! | t_mann wrote: | They do, it's called the ground floor. | Zardoz84 wrote: | "Bajo" in Spain | copperx wrote: | I've always called floor zero and everybody understands. | espadrine wrote: | In France, it is called the rez-de-chaussee. The "premier | etage" (literally translated as "first floor") is what | the US calls the second floor. | mananaysiempre wrote: | A particularly topographically challenged building in | Paris has exits to two enclosing streets end up on | different floors. The elevator is numbered -2, -1, rez- | de-rue [exit north], rez-de-chaussee [exit south], 1, 2, | ... . | childintime wrote: | Nobody knows that one. | | No elevator I've seen has yet taken a cue from UI design: | simply put the buttons within an outline of the building, | along with the local numbering scheme. | | No more visits to the serial killer lurking in the basement. | | The players in this market evidently have been operating at | T'ump levels of intelligence. /s | enobrev wrote: | You've got ...P3, P2, P1, G, M, 1, 2, 3... | shadowofneptune wrote: | In Tucson I've seen some buildings where the basement is the | first floor. You enter at floor two. | zajio1am wrote: | > The 1 makes a lot of sense in a human world, when we count, | we start at 1, we talk about the "1st", counting on finger | starts with 1, etc. | | It is more like counting from 1 is just a leftover from times | where zero was not commonly considered as number. Once one have | zero, it makes sense to use it as an initial ordinal (see e.g. | set theory, where zero is both initial ordinal and initial | cardinal number, way before computers). | | Another example is time and date, we start counting of days | from 1, but counting of hours (at least in 24-hour notation) | and minutes from 0. | | > Luis started explaining why Lua was 1-index with this | sentence: "The 1st argument ...." | | Note that for spoken language, it is "The first argument ..." | and 'first' is etymologically unrelated to 'one', but related | to 'foremost', 'front', so it make sense to use 'first' for the | initial item in the sequence even when using counting from 0. | steadicat wrote: | When talking about discrete things, 0 has a specific meaning: | it is the absence of things. It does not make sense to count | the 'first' element as the 0th. When you encounter the | 'first' element, how many elements do you have? 1. | | This is of course different for continuous quantities. When | counting seconds, for example, we should absolutely start | from 0. | kazinator wrote: | Is it machine-focused that we can convert a distance of 1.5 m | to 150 cm just by multiplying by 100? | | Maybe distances should be human-focused, so that no | displacement is equivalently expressed as 1 cm, 1 m, 1 km, ... | | Then converting a distance d from m to cm is (d - 1) x 100 + 1. | hougaard wrote: | ... but if you have something that's 150cm, that's not 151cm, | that's 150cm? | bentcorner wrote: | > _The 1 makes a lot of sense in a human world, when we count, | we start at 1_ | | As a kid I learned "one one-thousand, two one-thousand, three | one-thousand" when counting time out loud, but at some point I | realized this was incorrect. The prefix is the start of the nth | second but it isn't complete yet, so for example stopping in | the middle of saying "two one-thousand" you actually haven't | reached two seconds yet. | | My fix was to move the prefix to the end, so I say "one- | thousand one, one-thousand two, one-thousand three". | | In retrospect maybe I should have used "zero one-thousand, one | one-thousand, two one-thousand". | 8note wrote: | None one-thousand, one one-thousand, two etc | | Doesnt sound half bad | ziml77 wrote: | I don't think it's necessary incorrect to start at one there. | If someone asks you to count out 3 seconds, you're going to | say "one one-thousand, two one-thousand, three one-thousand" | and only at the end of the "three one-thousand" will you have | considered the 3 seconds to have actually elapsed. Basically | you're already accounting for the time it's taking you to say | it. Which to me seems better because if you do it the other | way because it gives a better heads up as to when that second | has been reached. | numlock86 wrote: | > It really comes down to a choice between a machine-focused | (0) or human-focused (1) approach. | | Just think of 0-based as offset-based and 1-based as index- | based. Both are intuitive just like that. I never get why | people arguing over this bring pointers and memory (or anything | computer related) to the table. No normal person is going to | understand that, but everyone understands that if you don't | move at all (0 offset) you stay at the first (index 1) item. | Add one and ... you get the point. | kccqzy wrote: | I must say in this case Google does it right: | https://cloud.google.com/spanner/docs/reference/standard- | sql... | | In Google standard SQL, to access an array it is simply not | allowed to put a number inside square brackets. You must | specify which way you mean. So `SELECT | some_numbers[OFFSET(1)], some_numbers[ORDINAL(1)]` is allowed | but not `SELECT some_numbers[1]`. | kergonath wrote: | That sounds actually great to avoid any ambiguity. At the | cost of a bit of verbosity, though. | dllthomas wrote: | But I think that still leaves open the question of "offset | from what?" | | If you move zero from the first element, you're still at the | first element... but if you move zero from the fourth element | you're still at the fourth element. If you move one from | _before_ the first element, you 're at the first element. | | I think you're more or less right, but I think we still need | something to motivate the first element as the point of | reference, and the machine focus is one way to do that. | lupire wrote: | In some languages/environments, the array is literally the | same as the pointer to the first element. | | Other languages are more sophisticated (like humans are!) | and can say that position 0 does not exist. An array of | size 0 has no elements. An array of size 5 has elements 1at | through 5th. An array of size N has 1st through Nth, | inclusive. | lupire wrote: | "ordinal" is preferred to "index", as "index" doesn't | naturally suggest starting at "1", or even restricting the | key to integers. "Ordinal" starts from 1, everyone agrees | (except mathematicians, of course :-) ). | pb7 wrote: | Ask 100 random people on the street and I'd be surprised if | even 1 knew the definition of "ordinal". It's an uncommon | word. | lupire wrote: | So is "array". What's your point? My point is that it is | unambiguous once you say what you are talking about. | pb7 wrote: | I disagree. The CS definition of array, sure, but if you | were to say "we have an array of options to eat", most | people with a high school education would know what you | mean. | LudwigNagasena wrote: | Do people not study grammar in American schools? I | thought all kids learn the distinction between cardinal | (one, two, three) and ordinal (first, second, third) | numbers. | Octoth0rpe wrote: | The English grammar that Americans study in school is | likely somewhat different than the English grammar that | is taught outside of America as the goal of the latter is | likely focused on helping students map their native | language onto English. I would agree that `ordinal` is | uncommon word for many Americans, but it wouldn't at all | surprise me if there were languages where the equivalent | word was far more common, and therefore its use and | translation was a part of standard English as a second | language curriculum. | [deleted] | pb7 wrote: | At the age that cardinal and ordinal numbers are taught, | kids simply don't remember "cardinal" and "ordinal", they | remember "one, two, three" and "first, second, third". | | 99% of the instances I've seen "ordinal" outside of this | thread has been in code/documentation. It is not a common | word in everyday language. | [deleted] | Joker_vD wrote: | And then the counting niceties come along: those perennial +1 | mistakes are caused by the fact that, e.g. 4 and 5 are _two_ | numbers but they are only _one_ apart. | kazinator wrote: | Offset-based lets you refer to an abstract location that is | after the last element without resorting to n + 1. | [ ] [ ] [ ] ... [ ] 0 1 2 3 n-1 n | | We can regard this n as a "virtual zero", and then make it | possible to index the n - 1 element also indexable as just | -1. The index -n then aliases to 0. | amalcon wrote: | "Offset-based" is bringing in pointers; that's the thing it's | an offset "from". "The beginning of the array" is just a | pointer. | | I suppose saying that does have an advantage over explicitly | talking about pointers, in that the word "pointer" is a piece | of jargon that has a lot of baggage. That's just avoiding | jargon, though, not really using a different model. | thayne wrote: | There are a lot of cases where a zero index makes sense. In | physics and math there are cases where you start the index at 0 | and others where you start at 1. And even some where you start | at -1. Which you use depends on what is most convenient for the | problem at hand. | HarHarVeryFunny wrote: | Yes, but "human-focused" 1-based indexing comes at a cost since | at the end of the day the CPU has to add (index * element-size) | to the array base address to get the address of the indexed | element. With a 1-based index there's additional overhead in | either having to subtract 1 from the index or to have a wasted | "element 0" to avoid the need to do that. | copperx wrote: | I assure you, that if we counted from zero, there would be an | instruction to add and multiply in the same number of cycles | as a multiply. | HarHarVeryFunny wrote: | That's not possible - the subtract and multiply need to be | consecutive (adjust index before multiply by element size), | so even if it was a single instruction it would still take | longer than a multiply that didn't have to wait for a | preceding subtraction. | | The only way to avoid the speed penalty would be either to | have a wasted element at offset 0, or to maintain the array | base address as (address - (1 * element-size)) to avoid | having to subtract 1 from the index when accessing. In the | latter case for dynamically allocated arrays the code would | still have to do a subtraction to adjust the pointer | returned by the memory allocator, but at least that would | be a 1-time penalty rather than per-element-access. | | Of course this is supposing a high level language where an | array is abstraction, not one explicity aliased to a chunk | of memory such as C where an array and a pointer to it's | first element are interchangeable. | copperx wrote: | That goes against my intuition. Multiplication in | hardware to this day relies on addition. Is one adder | going to add an extra cycle? Or would that time be | amortized? Take a look at slides 45-46 here. https://acg. | cis.upenn.edu/milom/cis371-Spring08/lectures/04_... | | Do you know the answer to that question? (I don't, but if | someone does, it will settle this issue). | Aardwolf wrote: | > human-focused (1) approach. | | TBH humans would have been better of if we were 0-based, it's | just a convention. And we have the confusing language where | "20th century" means 1900's. If we wanted to bring the | 1-indexing we use in language to the fullest extent here to fix | that particular issue, time counting would have to start at | 1111. Except that won't work once reaching 5-digit years. | | If we would start with "zeroeth" instead of "1st", then this | would have solved itself and 20th century would mean 20xx's. | airstrike wrote: | > where "20th century" means 1900's | | to this day I can't seem to be able to explain to people that | Jan 1 2000 was NOT the start of the new millennium, but | rather Jan 1 2001 | | https://www.latimes.com/archives/la- | xpm-2000-dec-26-mn-4810-... | analog31 wrote: | I always thought of the machine focus being that the location | of the first element was the location of the array plus zero. | jcelerier wrote: | At which number starts the first centimeter on a ruler ? | RunSet wrote: | At which number starts the zeroth centimeter on a ruler? | [deleted] | jcelerier wrote: | it's the first and it is 0, just like the first index in a | C array is 0 | Aardwolf wrote: | > human-focused (1) approach. | | TBH humans would have been better of if we were 0-based, it's | just a convention. And we have the confusing language where | "20th century" means 1900's. If we wanted to bring the | 1-indexing we use in language to the fullest extent here to fix | that particular issue, time counting would have to start at | 1111. Except that won't work once reaching 5-digit years. | | If we would start with "zeroeth" instead of "1st", then this | would have solved itself and 20th century would mean 20xx's. | | I especially don't understand why mathematicians use 1-based | indexing (for matrix rows/columns etc...). Like programmers, | they should see the advantages of starting at 0 (e.g. the | coordinates of subdividing into block matrices are simpler if | starting at 0). Mathematicians do start at 0 for the origin of | plots, after all. | OscarCunningham wrote: | > If we wanted to bring the 1-indexing we use in language to | the fullest extent here to fix that particular issue, time | counting would have to start at 1111. | | That's funny, but there's actually an elegant way to do it | called Bijective numeration | (https://en.wikipedia.org/wiki/Bijective_numeration). We're | currently living in the 1A22th year. | kevin_thibedeau wrote: | It has nothing to do with pointers and everything to do with | basic computer arithmetic. You can constrain the range of an | integer with a bitwise AND operation providing a cheap modulus | by power of two. In this regime, zero-based indexing is the | natural result. You have to make an adjustment for 1-based. | There are whole host of other operations that are simpler with | 0-based indexing. | | The problem it that most people, even programmers, don't | understand how computer arithmetic works and have fantasies of | mathematical number lines that the hardware only partially | simulates. You see this consistently in the post-Java crowd who | think that unsigned integers are some sort of unholy aberration | because the languages they've grown up went further to maintain | the fictional number line semantics. | tromp wrote: | > when we count, we start at 1 | | If I ask you to count the number of red balls in a bag with | only 3 yellow balls, then the initial count in your head is 0, | you inspect the balls one by one, never encountering a red | ball, and thus never incrementing the count. And then you | pronounce your final count of 0. So that's counting starting | from 0. | | What you call "starting at 1" is not so much the start as it is | the first increment, which need not arise. | xxs wrote: | I have used 1 based in basic/pascal and 0 based (well in pretty | much everything), 0 based effectively no off-by one mistakes. 1 | based - common. Most idioms - incl. forward and reverse | iterations work better, and are easier to remember with | inclusive/exclusive pattern | | Other than that - binary AND and power of 2 sized arrays are | the backbone of any hashtable. Overall modulus (binary AND) is | actually useful. | kazinator wrote: | In Western music theory, intervals are one based. No pitch | change is "unison"; one diatonic step is a "major second" and | so on. As a result of this silly state of affairs, an octave | occurs every 7 notes, even though the root "oct" means eight. | Furthermore, a "rule of nines" is needed to invert an interval: | e.g. inversion of minor 3rd is a major 6th (exchange | major/minor, subtract from 9). | OscarCunningham wrote: | And addition also gets broken. Like a third plus a fourth is | a sixth. | qsort wrote: | I don't think 1-based arrays are better notation, even | completely ignoring that code has to run on a machine. | | 99% of the times, the correct approach is to use iterators. | When you _really_ need indices (and you almost never do), 0 is | more practical, because it matches the "including start, not | including end" convention. | kazinator wrote: | > when we count, we start at 1 | | That is false; counting begins by initializing an accumulator | to zero. When you register the first item, the count jumps from | 0 to 1. | goatlover wrote: | Who sets an accumulator to zero and then adds one in everyday | language? | kazinator wrote: | For instance, someone who makes a fist with zero extended | fingers before counting. | | Or someone who simply becomes motivated to count something, | without making any utterances or gestures to that effect. | The motivation is followed by the persistent awareness that | nothing has been counted yet, which then changes to 1. | randomdata wrote: | _> when we count, we start at 1, we talk about the "1st"_ | | Although often with an implicit zero. Under typical North | American culture, your 1st birthday, for example, is more | accurately the first anniversary of your birthday. Your birth | is zero indexed. | drewzero1 wrote: | Oddly(?) though, most parents of young children don't refer | to a baby as being "zero years old." Rather, we break them | down into smaller units: two days old, six weeks old, four | months old. | throwaway821909 wrote: | It helps that change happens particularly fast at that age, | so the difference between newborn and 6 months is worth | mentioning. Later on the units go up again and we just say | "I'm in my 30s" :P | | On the other hand a computer/car/house can also be 10 years | old but not 0. | drewzero1 wrote: | True, a few weeks can mean a few milestones at that age. | It's still wild to me how quickly babies/kids develop. | Every week brings new abilities, experiences, and | emotions that weren't there before. | wruza wrote: | _On the other hand a computer /car/house can also be 10 | years old but not 0_ | | Really? When I buy a new PC, to me it will get 1 year old | only after a year. Before that it is just NEW. Is that | what you meant? | ellen364 wrote: | Demographers sometimes describe age as "the number of | completed years", which always struck me as a wonderfully | simple explanation. | atwood22 wrote: | No, birthdays are 1 indexed. Your Nth birthday is the day you | turn N years old. When you're 1 year old, you've been alive | for 1 year, not 2 years. | rcoveson wrote: | No, old calendar systems are one indexed. In those system, | there is literally no year zero; the first year is year | one. This leads to crazy things like year 100 being part of | the "first century" and year 101 being part of the "second | century". | | That is not the case with age or birthdays which are, | thankfully, zero indexed. The first year of human life is | age=0, birthdays=0. | [deleted] | lupire wrote: | It's not "crazy". No one care about which century X00 is. | The term "century" doesn't have enough sig figs. X00 is | "the turn of the century". | rcoveson wrote: | If you don't care then sure, it's not crazy, but if you | did care then believe me, it is crazy. Crazy enough that | astronomers[0] and software engineers[1] rebelled against | the historian's practice and renamed the years preceding | 1 AD in the proleptic gregorian calendar year 0, year -1, | year -2, et cetera. A major benefit of this is it allows | the leap year pattern to stay consistent and the rule to | remain legibile for all years, going back before 1 AD. | It's also nice because it lets us say "the 90's were the | last ten years of the 20th century" and be correct. | | 0. | https://en.wikipedia.org/wiki/Astronomical_year_numbering | | 1. https://docs.oracle.com/javase/8/docs/api/java/time/te | mporal... | randomdata wrote: | The moment you are born you are 0 years old (or perhaps | 0.75 years old, but we don't usually recognize that). We | count from zero in this case, at least implicitly. | | In some cultures you are considered 1 the moment you are | born, so the zero indexing isn't universal here, but | typical in North America as noted earlier. | atwood22 wrote: | No, we don't count from 0. That's like saying we start | counting a baker's cup from 0 because you can have half a | cup. | emaginniss wrote: | Ok, use the baker and cup as an example. If you have an | empty cup and put half of a cup of flour in it, you now | have 0.5 cups of flour. Notice the zero before the ".5". | That is us, normal humans, realizing that until you add | enough to have 1 of something, you have between 0 and | 0.999 repeating. | kazinator wrote: | The counting activity doesn't begin when the first item | is registered; it begins when the counter is initialized | to zero. A decision is made to begin counting, along with | the realization that nothing has been counting yet. | That's when counting has started. When the first item is | seen, the counting is then continuing. | | Suppose your job is to count some events. You check in | for work at 8:00 a.m., but the first event has not | registered until noon. By your logic you should not be | paid for four hours, because you're paid to count, and | counting started at 1. | anigbrowl wrote: | You're still thinking like a computer. Most people think | of counting in terms of 'here are some apples, how many | exactly?' | | If you just look at an empty space, the # of apples is | equivalent is equivalent to the # of dinosaurs, but | they're only equivalent by their absence. | atwood22 wrote: | No, the mathematical definition of counting (i.e. whether | or not a set is countable) involves mapping to the | natural numbers, which doesn't include 0. | kazinator wrote: | I don't think your definition is complete. We can count a | set by mapping its elements to the natural numbers, and | then identifying that number which is highest. However, | we must have a provision for identifying zero as the | highest when the set and mapping are empty. | 8note wrote: | Math counting doesn't care where you start. You could | start -400 if it's useful for the problem | lupire wrote: | You can name things however you want, but there is a | canonical bijection to zero-based ordinals. | | https://en.m.wikipedia.org/wiki/Ordinal_number | goatlover wrote: | What counter? You're saying a counter exists before | people start counting? Is this a form of mathematical | Platonism? | kazinator wrote: | A counter can be lazily instantiated just before the | first item is counted. | lupire wrote: | What does your stopwatch say right now? | | Your pedometer? | | Your traffic clicker? | lupire wrote: | Are you sure? | | We are talking about the he numbering, not the work- | doing. | | You start _waiting_ at 8, and you wait between events. | But you only count (increment) when an event happens. | | The 0 comes for free when you are _ready_ to count (hello | golang and C++, as well as human intuition). | | When you count stars in the sky you don't say "0, 1, 2". | | You say "..., 1, 2", or if no stars show up, you say | "there are 0" after timer expires. | kazinator wrote: | > _But you only count (increment) when an event happens._ | | Increment what? | | > _When you count stars in the sky you don 't say "0, 1, | 2"._ | | No, you say, "I'm going to start counting stars now. | Okay, 1, 2, ...". | | The preparation part is the zero. You counted stars | before and reached some number; you're not starting at | that number. | 8note wrote: | I start with a empty cup, then I fill it up to 1 cup. | | I then put it in an initially empty bowl | bregma wrote: | When I'm baking I start by zeroing the scale, then adding | enough flour to reach 500 g (or whatever the recipe calls | for). That's counting from zero. | randomdata wrote: | If we (speaking as a North American) count from 1, does | that mean other cultures (e.g. Korean) count from 2? | atwood22 wrote: | No, it just means we have a different notion of what a | year is in regards to age. Similar to how different | cultures can use different units of measurement for | length, mass, etc. | randomdata wrote: | Yes, exactly. One of which carries an implicit zero | indexing. The date of birth doesn't disappear just | because you decided to use a different measuring device. | atwood22 wrote: | No, it doesn't carry an implicit 0 index. Measuring age | (in the West) is like measuring distance. You start at 0, | but that doesn't mean the first item is at index 0. | randomdata wrote: | If you took a standard ruler, a measurer of distance and | which has literal index marks painted on it, and placed | items along it, the item found at the head of the ruler | would be found at the 0th index. You're quite right that | we think of birth and its anniversaries in the same way. | kazinator wrote: | What do you do for a living, and why are they paying you | not to understand this? | bmacho wrote: | Can't they just .. disagree? | | Birthdays are clearly 1 indexed, the first birthday is | indexed with 1, and not with 0. | ziml77 wrote: | They day you're born is birthday number 0 | bmacho wrote: | Exactly. | | Birthday[0] gives you an out of range exception, since | there is no birthday called 0th. Birthdays are | [first,second,..] indexed from 1: brithday[1] = first, | birthday[2] = second, and so on. That's what indexing a | series from 1 _means_. | atwood22 wrote: | Do you know the definition of countable? A set S is | countable if there is a one-to-one mapping from S to N | where N is the natural numbers. Do you know that 0 is not | a member of the natural numbers? We literally start | counting at 1 by definition of countable. | kazinator wrote: | An empty set is countable; it has an empty mapping to the | natural numbers. Its cardinality is zero. | lupire wrote: | Nope. | | Is the empty set countable? (Yes.) | | Dictionary: | | nat*u*ral num*bers the positive integers | (whole numbers) 1, 2, 3, etc., and sometimes zero as well | | Countable: https://en.wikipedia.org/wiki/Countable_set | | Set theory: | | https://en.wikipedia.org/wiki/Ordinal_number | atwood22 wrote: | From your own link on countable sets: | | > Equivalently, a set S is countable if there exists an | injective function f : S - N from S to N; it simply means | that every element in S corresponds to a different | element in N. | | Defining N is usually done via a successor set, on which | case 0 makes no sense to include. | themacks wrote: | Typical counting of things starts from 0. If you count | apples you implicitly start at zero and add 1 for each | apple. If you count age, you start at birth (0) and count | years; one for each birthday. That isn't zero based. The | difference is the index of the item between the starting | point and the next item. In zero based this item is | number 0, in one based, this item is number 1. The first | year of life is generally considered the year following | birth. | dylan604 wrote: | >If you count age, you start at birth (0) and count | years; one for each birthday. | | nitpick: unless you were born on Feb 29. | copperx wrote: | I didn't know that. Do you get to be 1 year old if you | are born on Feb 29, to account for leap years? | dylan604 wrote: | You're just 1/4 of the age of everyone else born the same | year. You have the same number of laps around the sun as | those people, but you've definitely had fewer birthdays. | It's a common joke for leap year babies. | somat wrote: | I just dealt with this problem(how to store periodic | events(including birthdays)). It is a surprisingly | difficult problem. After reading up on postgres interval | types my latest attempt uses them to store events, where | a per year event(like a birthday) is stored as "2 months | 15 days". it turns out the postgres project has put quite | a bit of thought into making interval types work as | expected with regards to months, not an easy task when | you consider how difficult it is to treat dates | mathematically. | | The nice part is that now February 29 "just works" the | downside is the impedance between how months and days are | numbered and a how an offset from the epoch(beginning of | the year) is defined. January 3rd(1-3) is stored as "0 | months 2 days" as when it hits, 0 months have passed and | 2 days have passed. | | So the specific case of February 29 hits when 1 month has | passed and 28 days have passed. 3 years out of 4 this | will be the same as "2 months 0 days"(3-1) but every | forth year this will be(2-28). As an aside, and the | specific reason I went with interval types, every event | past feburary 29 works just fine with or without a | leapyear, that is, the extra day in the middle does not | mess up the offset to days after it. | | Honestly I curse a little as I wish months and days were | 0-based. At least clocks get this right, almost, 12 hour | clocks are a special breed of stupid. start at 12, then | go to 1 and proceed up to 11. 24 hour clocks properly | start at 0. The worst part about 12 hour clocks is that | it is almost correct, replace the 12 with a 0 and it | every thing be the same but now it makes sense from a | moduler math point of view. | | A special curse is reserved when I think about how there | is no year zero. | https://www.postgresql.org/docs/13/functions- | datetime.html#F... | goatlover wrote: | > If you count apples you implicitly start at zero and | add 1 for each apple. | | If that's the case, then how did the ancient Greeks or | Romans count before zero was an acceptable concept in | their counting system? | unbalancedevh wrote: | By describing it in other ways, I imagine: "How many | apples do you have?" "I don't have any." | brianzelip wrote: | So how old is a not-yet-1-year old? | atwood22 wrote: | N days or N months depending on how old the baby is. | rcoveson wrote: | And before an hour has even passed, we'd probably say | "minutes old" or perhaps "not even an hour/day old", all | to avoid saying "zero days/months/years old". But some | might still say zero days old, and they'd be both | understood and correct (at least logically if not | stylistically). That's the "implicit zero" everybody is | talking about. We avoid saying it, but that's just a | convention of communcation. Logically it's there. You're | zero days old before you're one day old. | randomdata wrote: | And it turns out that 0 days, 0 months is 0 years. | xxs wrote: | Your mistake is using years - use milliseconds (or | nanoseconds) when you wish to express a duration. Years | don't even have the same duration/length (leap years, and | leap seconds) | nomel wrote: | Elapsed time timers start at 0. Time is continuous. The | elapsed time being "out of the womb", that we call "age", | starts near 0. Five minutes after birth, the baby has | been in the world for, or it's age is, five minutes. If | someone asked how old a new baby is you could hear "3 | weeks". | | Another definition might be from conception. But birth | being "one year old" is illogical. The sperm didn't even | exist yet, one year before birth. | csours wrote: | Your birth day is the day you are born. | | Your first birthday is the first anniversary of your birth | day. | | We celebrate the anniversaries of our birth day. | treis wrote: | Yep, clearer in Spanish. They say cumpleanos which | literally means completed year. | wruza wrote: | Haha, this thing is messed up. Your "first birthday" is | technically second, because the first was at your, well, | day of birth. But we people love to complicate things and | count 1st birthday as a number of annual celebration events | _after_ the first mm-dd of birth. Off by one as it is. | hougaard wrote: | Yeah age is confusing even for non-computer-folks :) | | If you have 4 classes in school today, you would never talk | about the 1st class as number 0, the last one is the 4th, not | the 3rd. | [deleted] | randomdata wrote: | Although, there is a fifth state in your example: When you | are not in class. Which is different to an empty set that | implies nothingness. When it comes to age, 0 being birth | works well because there is truly is nothingness (from your | perspective) before birth. When counting from 1 there is | suggestion that there are variables that aren't worth | speaking of because they are obvious. | goatlover wrote: | Assuming there is nothingness for the fetus the entire | nine months in the womb. For that matter, I can't recall | being younger than four, so it's all nothingness before | then. | randomdata wrote: | Not really. Perspective isn't scientific and often | cultural. Koreans, for example, famously have a different | take and use a different counting systems to accommodate. | | I am assuming that the reader is biased towards the | average HN user. That won't always work for everyone who | will come across my comment, but close enough for an | unpaid contribution. I'm not about to write a novel to | make sure I catch every edge case. | yongjik wrote: | That's why I prefer the Superior(TM) Korean age counting. You | are one year old when you're born (it's your first year!). | You are two year old on the next New Year's day. | (Congratulations, it's your second your now!) | | So, if you're born on December 31st, you're two years old the | next day. (I see no problem, but apparently some people are | hung up on such minor details. I can't fathom why.) | BeFlatXIII wrote: | > I see no problem, but apparently some people are hung up | on such minor details. I can't fathom why. | | Americans and their alcohol laws... | galangalalgol wrote: | Doesn't Korea use the same new year as China? Usually | second new moon after winter solstice. | smegsicle wrote: | hung up on minor details! | dllthomas wrote: | There's nothing wrong with the definition per se, but | there's the question of what purpose you're putting it to. | We should expect more similarity from two "newly 2" | children with the "western" system than the Korean one. | tromp wrote: | > You are one year old when you're born (it's your first | year!) | | That makes no sense to me. It's also your first century. | Does that make you one century old? Of course not! The | moment you're born, you're not even one hour old, let alone | one day. | BuckRogers wrote: | They must like rounding up. I guess it depends how they | refer to it in their language. If it's "he's in his 1st | year", that's a big difference from, "he's 1 year old". | I'm wondering if the parent comment simply doesn't know | Korean or only knows it somewhat to misconstrue the | culture behind this. | | It could be though that Korea simply never encountered | the Mayan or Arabic civilizations as most did encounter | one of those two in history, who are famously known to | have independently discovered the concept of zero. | | Birth of an array can only logically be defined as index | zero, the same as a child. The concept of zero was not | universal globally and Korea is pretty isolated. | OscarCunningham wrote: | Except that we actually do use this system for years. | Thus 1 BC (the first year BC) was followed by 1 AD (the | first year AD). Also for centuries, as in 'the 20th | century' being the years 1901 to 2000. | hathawsh wrote: | A more sensible English translation from Korean would be to | use the phrase "in year X" rather than the phrase "X years | old": a newborn is in year 1; after 12 months they are in | year 2; etc. | | In fact, this whole discussion is more about a choice of | phrasing rather than the numbers. When indexing arrays, | sometimes we're talking about an _offset from the first | element_ (starting with "0"), and sometimes we're talking | about _ordinal element numbers_ (starting with "first"). | Some programming language designers found that offsets are | more useful (because that choice tends to simplify the | underlying arithmetic), while others found that ordinal | numbers are more useful (because the word "first" should | mean "1", to simplify communication between people). | OscarCunningham wrote: | Right. I try to refer to a[n] as 'element number n' | rather than 'the nth element'. | gumby wrote: | This system is used for racehorses as well. | lupire wrote: | The first floor in a USA building is not where a European | would expect. | anigbrowl wrote: | No. Your age is 1-indexed. It's a 'birthday' in English and | German ('geburstag'); in French it's 'anniversaire', and so | on. But pretty much everyone indexes age from 1. The fact of | your birth is the transition from (legal) non-existence to | existence, the equivalent of a dimensionless point. | wruza wrote: | Age is definitely 0-indexed - a newborn and exactly 1 year | old differ by a year. People also count months during the | _first_ year, which is still 0 years old. As in 00:xx is | the first hour, and 01:xx is the second. If you 're 30 | years old, it's your 31st year of life now. | | But gregorian epoch itself is 1-based. 1AD (0001-01-01) | goes right after 1BC (-0001-12-31). There was no 0000-mm- | dd. That's why 3rd "millenium" and 21st century started at | 2001-01-01 and _not_ at 2000-01-01. YYYY means not how many | whole years already passed, but _which_ incomplete year | goes right now. On the other hand, your age means "whole | years passed since birth [plus maybe a few months]". | ethbr0 wrote: | It's fundamentally a distinction between end-index and start- | index. | | Most human counting uses end-index. I.e. "1" is _after_ | 1-thing (has passed, is physically obtained, etc.). | | Most computer counting uses start-index + length, for | efficiency and to better generalize. I.e. "1" is at the | memory address immediately _before_ the "1"st item. | | Which ultimately creates the "0 index is 1st thing" | linguistic confusion. | | PS: Also, language predates computers by a few years, and the | concept of zero is hard. | smegsicle wrote: | good take! | | i think a more accurate and complete idea is that humans | refer to a thing _in its entirety_ , with things being | lined up and scanned in order as only a potential | convenience | | if you ask someone to identify an object, they'll point to | the middle (or center of the most important component) of | the object, not to the 'start' or 'end' of it in their | field of vision.. | | that said, the human perspective is subtle and convenient | in completely different ways to how a computer manages | memory, and this 'end-index' idea seems like a useful way | to map the human whole-object perspective to a linear | memory-index perspective | Stratoscope wrote: | Rulers too. A ruler starts at 0, not 1. | dividuum wrote: | Not all of them do: | https://twitter.com/blinry/status/1550920690529968128 %) | Stratoscope wrote: | Nice! I want a Lua ruler now. | anigbrowl wrote: | That's because it's dimensional. How long is the shortest | possible ruler? | dalmo3 wrote: | 1 planck length, and... It starts - and ends - at 1? | Tagbert wrote: | Birthdays are anniversaries. Anniversaries are annual | activities when we celebrate/honor past events. They do not | include the event itself. The first anniversary is 1 year | after the initial event. | randomdata wrote: | _> Birthdays are anniversaries._ | | Indeed they are, which is why I literally said so in the | previous comment. Did you forget to finish reading it? | | _> They do not include the event itself._ | | That is true because the event itself is implied | information. There is no value in speaking of it. If you | stand before us, we can be certain that you had a day of | birth (your 0th anniversary). We don't necessarily know how | many times you've gone around the sun following that, | however, so that is where we find value in communicating | additional information. | | If you were counting apples, there is the state where you | have no apples (index 0), the state where you have one | apple (index 1), the state where you have two apples (index | 2), etc. When counting you don't need to worry about index | 0 because the no apple state is naturally implied. It only | becomes interesting and worthy of communication when you | have at least one apple to speak of, thus you start at 1. | The state found at index 0 is still implicitly there, | though. | lupire wrote: | If I care about apples (for my lunch, or my store), I | care about the difference between having 0 of them and | not having bothered to count yet. | | 0!=null | randomdata wrote: | If no apples is the unusual state, like you expected to | find an apple in your lunchbox but someone ate it without | your knowledge, then certainly there would be reason to | communicate the no apples state. It is ignored in | communication when it does not provide useful | information, but it is not forgotten. The 0th index is | implicitly there. | anigbrowl wrote: | Come to the infinity store - we literally sell | everything! (some items may be out of stock) | randomdata wrote: | Yes, the infinite state is also implicitly found within | the state set. Conveniently found at the infinity index. | sokoloff wrote: | Yes, that's the explanation for _how_ we count them as we | do, but it has no greater weight (and I'd argue less | weight) as to _why_ than saying whether a[0] or a[1] should | be the first element in an array. | | I say it has less weight as birthday is a compound word, | the root words of which suggest that your first birthday | could logically be the day of your birth rather than a year | after it. | | My first weddingday was not a year after I got married. My | first graduationday was not a year after I graduated. | rmason wrote: | Actually in not all languages do arrays start at 0. In ColdFusion | for example arrays start at 1. I've never been able to receive a | reason as to why CF's original author, J.J. Allaire, did it that | way. | amilios wrote: | also Lua and R. | ur-whale wrote: | And Julia, an otherwise nice language. | dark-star wrote: | Simple answer: because everything in computers starts at 0. | Address 0 is the first byte of memory, etc. | | You can now ask, "why does everything start with 0"? I guess | because it gives you nice round (base-2) numbers. With 4 bits you | can have 16 different "numbers", either 0 to 15 or 1 to 16. | However, representing the number "16" in binary requires 5 bits, | so you need an additional bit for the same number of elements. So | representing 4 bits as 0 to 15 makes more sense | User23 wrote: | Pascal's arrays start at 1, at least by default. | wvenable wrote: | Pretty much all variants of BASIC have arrays starting at 1. | hwayne wrote: | Pascal is a variant of ALGOL-60, made in part because Wirth | thought ALGOL-68 was way too complicated. BASIC instead comes | from the FORTRAN line. | JKCalhoun wrote: | I think a language needs to decide if it is "high level" or | if it is instead a convenience language on top of assembly. | | BASIC and Pascal I am sure would have been considered a high- | level language in their day and naturally would have arrays | be 1-based. | | C on the other hand.... | unnouinceput wrote: | This is false. Pascal arrays start at whatever you want. As for | what is happening behind closed doors (aka linker), those start | at zero, but with an offset kept separately (that's why C blew | out of the water Pascal in terms of speed when looping through | an array). And in Pascal you cannot create a dynamic array with | anything other than 0-based. | | You are confusing arrays with strings. Those used to start at | 1, but since Unicode took over (~2007) strings are implemented | as zero-based too (even though you can still think of them as | 1-based when writing code). | | Also in Delphi, when creating a cross-platform application, | strings are treated as 0-based, with even multiple locations in | documentation stressing this importance due to having enough | differences between classic VCL and the new kid on the block | (aka FireMonkey). | Koshkin wrote: | The _first_ element having the index zero may be natural or | unnatural _depending on the context_. In mathematics, we count | the rows in a matrix starting from 1, but we count the monomials | in a polynomial starting (or ending) with 0. Generally, there is | less need to use zero as the starting index: the Common Era does | not have "the year zero" (there, -1 is followed by +1), etc. | csours wrote: | This reminds me of arguments about male -> female and man -> | woman (and human etc). Without offending anyone's delicate | sensibilities - you may note that there is a short version and | long version of those words, suggesting that the longer version | is derivative of the short version. | | However, when you examine the origin of the words, that is not | the derivation. The derivation and path to English is quite | complicated. You may feel a sense of righteous indignation or | righteous repudiation on this topic. I would gently suggest | deferring that feeling because I think the story is very | interesting to follow. | | That is not the end of the story though. The reason those pairs | of words stuck around is almost certainly because it makes a | consistent mental picture. | | Bringing it back to the topic at hand - "Why we use 0" - because | it works. There are many times when it has been evaluated, and at | least to the people who design languages, it is more mentally | appealing. | | https://www.etymologynerd.com/blog/man-vs-woman | | https://medium.com/interesting-histories/interesting-histori... | zwkrt wrote: | I really fail to understand what the etymology of sex and | gender classifications has to do with array based indexing. | csours wrote: | > "Bringing it back to the topic at hand - "Why we use 0" - | because it works. There are many times when it has been | evaluated, and at least to the people who design languages, | it is more mentally appealing." | | The linked post is not just about a technical decision, it's | about a social history. | | The conclusion of the linked post: | | > "Lessons | | Things can have more than one cause. Don't trust easy | explanations. | | Always look for information that refutes your theory, not | just information that supports it. Hoye stopped as soon as he | had a satisfying answer and didn't keep researching. | | Don't be a dick. | | It is tragically easy to trick me into doing free research." | codefreeordie wrote: | Arrays start at 0 because they're really just pointers. "[x]" is | just shorthand for "+ x * sizeof". The first element is the one | stored at the pointer address (0 sizeofs ahead of the pointer, | the next element is stored 1 sizeof ahead of the pointer, etc. | giraffe_lady wrote: | That answers something like "what are the technical benefits to | zero-based arrays" but not "why are zero-based arrays such a | strong convention in programming languages." For that you'd | have to read the article I guess. | JKCalhoun wrote: | Or it could be: | | "technical benefits to zero-based arrays" -> "why zero-based | arrays are a strong convention" | | Article mentions that Hoye says as much but is dismissive of | it. I am not sure why he would be so quick to dismiss. | vidarh wrote: | In C, "a[x]" is effectively syntactic sugar for just "*(a+x)" | (conversion rules for "+" means you don't need the sizeof). It | also means you can reverse it and write e.g. "5[somearray]" if | you really want to make developers want to throw rocks at you. | yonrg wrote: | hehe, that was me :) when I was young. | nicoburns wrote: | That's just convention though. There's no reason "[x]" couldn't | have been defined to be "+ (x - 1) * sizeof". There would be no | runtime cost to this, and the compile time penalty would be | tiny even on ancient systems. | nwlieb wrote: | Is `(x - 1)` not a runtime cost if `x` is a runtime variable? | vikingerik wrote: | Not on many instruction architectures - addressing modes | often support adding/subtracting a constant. | demindiro wrote: | I find 0-based indexing easier to work with when working with | (dynamically sized) multi-dimensional arrays. For example, with | 0-based indexing getting an element at (x, y, z) can be done with | a[z * h * w + y * w + x] | | But with 1-based indexing you need to substract one first from | each component except the last: a[(z - 1) * h * w | + (y - 1) * w + x] | bregma wrote: | If you ask people which floor of building they're on, it's going | to depend on which country they're in. In North America, at | least, the first floor you walk into (in a sane city: I | understand there are some which do not qualify in this respect | due to hills or historic disaster recovery) is the first floor. | On other continents, you enter the ground floor and need to take | stairs or an elevating device to get to the first floor. | | "Natural" zero-based counting at its best. | ajuc wrote: | The ground floor is 0. The floor above 0 is 1. The floor below | 0 is -1. Anything else is crazy TBH, the whole point of integer | numbers is to count things that start at a defined point and go | opposite ways. Why shift it and then reinvent weird pseudo- | negative numbers like S1? | | But then again people measure distance in feet and write dates | as month day year :) | jccalhoun wrote: | It would be nice if this was the case. In grad school I | taught in a building that was on a hill and had once been | separate buildings so different entrances were on different | floor and the transition between the former separate | buildings was 4 stairs. | | So there was a floor with rooms numbered 1xx and 0xx. There | was also a floor below the 0xx floor. They just numbered it | 00xx. And you could enter the building on any of those floors | depending on what door you picked. | | The class I taught was in 0005. Room 005 was someone's | office. So on the first day of every semester we would have | students waiting outside the door of 005 instead of 0005... | hbn wrote: | You'd think if they had to go below 0 they could just | prefix with a letter, like B (Below? Basement?) B1, B2, | etc. | adrianmonk wrote: | Counterpoint: because floors are sum types. | | Floors 1 through 10 are "regular" floors. L is the lobby. P1 | through P3 are the parking (basement) levels. | | So you have three types: regular, lobby, and parking. And the | elevator labels are of type regular | lobby | parking. | | (Now you can't disagree with me because sum types are popular | on HN, and I have framed this in terms of sum types.) | ajuc wrote: | Sum types don't automatically define ordering between the | possible values AFAIK? So in your implementation you'd have | to manually define the up: (regular | | lobby | parking) -> (regular | lobby | parking) | down: (regular | lobby | parking) -> (regular | lobby | | parking) | | and which_way: (regular | lobby | | parking) x (regular | lobby | parking) -> direction | | If you use subset of integers you can just use operators | inc, dec and <. | | Yeah I know it was a joke. | adrianmonk wrote: | If I build a building in the shape of a double helix, | what order are the two floors in? | | Hmm, are there actually an infinite number of floors? Do | we need to switch to floating point? | ajuc wrote: | > If I build a building in the shape of a double helix, | what order are the two floors in? | | Why separate the floors that are on the same level? | | > Hmm, are there actually an infinite number of floors? | | I assumed there isn't and that we use a subset of | integers. If you have infinite number of floors - feel | free to use full set of integers (if you have enough | memory that is). | | > Do we need to switch to floating point? | | No point, if you have more than aleph0 floors - floats | won't help you. | GnarfGnarf wrote: | The Patterson Building at Acadia University in Wolfville, NS, | has a basement and four floors. The rooms on the first floor | are numbered 1XX, second floor 2XX, etc. up to the top floor | 4XX. | | The elevator, however, goes from floor '1' (the basement), to | floor '5' (the top or fourth floor). | | This really confuses visitors. | | The Elevator Mafia want $10,000 to fix it. | perlgeek wrote: | A big international corporation (Siemens) had, at one point, | standardized their buildings world wide to have room numbers | starting with 2 on the ground floor, 3 on the floor above etc., | leaving space for two basements. | | All room numbers were 5 digits, and skipped numbers if there | were multiple windows in one room, based on the theory that | such a room might later be sub-divided, and wanting to avoid | renumbering of rooms down the hallway. | | (I encountered this around 2003, so might have well changed | since then; didn't find any references only with a quick | search). | mywittyname wrote: | I worked for them relatively recently and didn't encounter | this; or at least never noticed. Then again, our office | building was an open office plan where desks next to the | windows and rooms (conference or office) were all in the | center of each floor. | KineticLensman wrote: | When I was at Leeds University the ground floor of the Physics | Admin building was Level 6 (it went up to Level 11). It was | built on a hill and according to legend this allowed room for | expansion (which never happened) down the hill without | requiring negative floor numbers. | | To add to the fun the only continuous corridor through the | entire T-shaped building was on Level 10, one end of which (the | base of the T) was at ground level on its part of the hill. | There was a famous 'kink' in the middle of the top / cross-bar | of the T (apparently the longest corridor in Europe) because | they started building from each end and were slightly off. | bluetwo wrote: | I always said it was an argument between the counting of things | versus the relative offset of things. | | This is a great example. | levodelellis wrote: | I call `array[0]` the first element. I don't know what you'll | think of that. | | I wonder how many multiples of people who like arguing about | starting from 1 vs 0 and how many people were confused for more | than a day | systemvoltage wrote: | I've been living in North America for decades. Every building | has G (zero). This is the floor that you walk into and has a | lobby. The next floor up is 1 as such is labeled in the | elevator. | | So your initial assumption is incorrect from my experience. | silisili wrote: | This is not my experience in the US. Most places either have | G or 1 for the first floor. Then 2 for the next. So some | elevators say G, then 2, 3, and so on. | | I've seen setups like you mention, but they definitely aren't | the majority in places I've lived. | jwarden wrote: | What city are you in, out of curiosity? | systemvoltage wrote: | SF Bay Area (currently), but have lived in several major | metro areas. | pklausler wrote: | Because sometimes we number things, and sometimes we count | things. | hcrisp wrote: | Dijkstra's answer (linked in the article) is best: | | "When dealing with a sequence of length N, the elements of which | we wish to distinguish by subscript, the next vexing question is | what subscript value to assign to its starting element. Adhering | to convention a) yields, when starting with subscript 1, the | subscript range 1 <= i < N+1; starting with 0, however, gives the | nicer range 0 <= i < N. So let us let our ordinals start at zero: | an element's ordinal (subscript) equals the number of elements | preceding it in the sequence. And the moral of the story is that | we had better regard --after all those centuries!-- zero as a | most natural number." | | https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E... | intrepidhero wrote: | It could just as easily be 1 <= i <= N and then I wouldn't have | to remember that the lower bound is inclusive and the upper | exclusive. | layer8 wrote: | Then the delta of both bounds (N - 1) wouldn't equal the | length of the range (N). The inclusive-exclusive convention | is used in order for `end = start + length` to hold. | Jtsummers wrote: | Why does that matter when the starting point is 1? In that | case, you don't need the delta because you have the length | already. In the case of a 0-based range you also don't need | the delta, though you will want to use the inclusive- | exclusive convention so that you get the length "for free". | 1 <= a <= N -- N = length, no delta 0 <= a < N -- N | = length, no delta | | You only calculate the length when dealing with other than | 0- or 1-based ranges. There, the inclusive-exclusive | convention is very handy as you point out. So if we're | fixing the initial offset at either 0 or 1, then use the | appropriate convention for that offset. If we let the | initial offset float, then the inclusive-exclusive makes | sense. | layer8 wrote: | It matters whenever you need to process a proper subrange | of an array, and that shouldn't be different from when | the subrange happens to be the whole range. It's simpler | if the same convention is used in all cases. | | E.g. in Java, a typical example is that OutputStream has | the following two methods, where the first can delegate | to the second, and the second (which write the specified | subrange of the array) can easily calculate the number of | bytes to write: int write(byte[] bytes) | { return write(bytes, 0, bytes.length); } | int write(byte[] bytes, int start, int end) { | int length = end - start; ... } | Jtsummers wrote: | I addressed that: | | > If we let the initial offset float, then the inclusive- | exclusive makes sense. | | But you replied to someone using inclusive-inclusive for | 1-based arrays and complained about the delta not | matching the length. Which is a nonsensical complaint, | you have the length already why would you need to | calculate anything? | layer8 wrote: | In case of the subrange you don't have the length (or you | conversely have the length but not the upper bound), and | you don't want to use different conventions based on | whether you process the subrange or the whole range. I'm | not sure how I can make it clearer. | thomasahle wrote: | Closed ranges (with both ends inclusive) are super annoying | to work with. You can represent the empty range (unless you | are willing to do [i : i-1]), and they don't compose like | half open ones: [a : b) + [b : c) = [a : c). | elikoga wrote: | cannot? | goatlover wrote: | I don't understand why 0 <= i <= N wouldn't have worked | instead, since you already have a less than or equal operator | at 0. | weavejester wrote: | That would give a sequence of N+1 elements, though. Confusing | if you had a function like range(N), for example. | goatlover wrote: | Why, it would be an inclusive instead of exclusive range. N | is the last element, so no reason for N+1. | weavejester wrote: | If we use inclusive ranges where 0 <= i <= N, then | len(range(N)) == N+1. | | e.g. len(range(3)) == len([0, 1, 2, 3]) == 4 | beardyw wrote: | Starting at one led to the whole "2000 is not the millennium" | thing, as there is no year zero. | ziml77 wrote: | Even more painful is that the 2001 began the 21st century, not | the 20th. | jfmc wrote: | The general term of arithmetic and geometric sequences seem | simpler when indexing from 0 rather than 1. I do not think that | '1' is more human focused for anything than '0'. | spullara wrote: | 0 is offset based. 1 is index based. | thetwentyone wrote: | This is my take and when working directly with computer | memory/addresses, 0-based is most convenient. For working with | data/stuff at a higher level, 1-based is more natural and | convenient. | tomkaos wrote: | Worst than 0 and 1 is to have the choice. In Visual Basic 6 you | have the option between the base 0 or 1 for each module. It make | debugging a nightmare and you can create bug just by copy/pasting | code from one program to other with a different base index. | GuB-42 wrote: | You also have the choice in Perl, because of course, it is | Perl. | | The old way of doing it was setting the $[ variable to 1. You | can actually set it to any value, in case you prefer to start | your arrays at 42. It is now deprecated but you now have | Array::Base that offers similar functionality. | | Use it if you absolutely hate the person who will read your | code, as if having someone read Perl code wasn't hateful | enough. | hoosieree wrote: | One of the least-loved APL features is the fact that you can | change the index origin at runtime. | diego_sandoval wrote: | Because otherwise you would be wasting a perfectly good number | for no reason, which means you need to use more bits to do the | same thing. | | To write 4 numbers (including zero) you only need two bits | 0: 00 1: 01 2: 10 3: 11 | | To write 4 numbers if you avoid using the number zero, you need | three bits 1: 001 2: 010 3: 011 | 4: 100 | | If you extrapolate that a little bit, you'll realize that you'll | need two bytes (1 Byte + 1 bit from another byte) to store the | indices of an array with 2^8 elements, which is just dumb. | | Some of you might be thinking: you don't need to store it the | same way it's written, you can just substract 1 from whatever the | user typed and convert it behind the scenes. | | Yes, you could subtract 1, but then you would be making the whole | system more complex, opaque, and unelegant, while hiding | information from the programmer for no good reason. | divbzero wrote: | The same applies to counting in other bases too. For instance, | in 1-indexed counting grids for kids, the last column always | feels out of place. | | 0-indexed decimal grid: 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 96 97 98 99 | | 1-indexed decimal grid: 1 2 3 4 5 6 7 8 | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | 97 98 99 100 | anigbrowl wrote: | Are you sure it doesn't just look that way because you are | used to monospaced fonts? Ask a kid to show you their zeroth | finger. | TOGoS wrote: | As a kid, I saw these things often on multiple-choice test | sheets. The tens digit at the end of each row not matching | that at the beginning always seemed awkward, and I wondered | why they didn't just start at zero. This was long before I | did any programming. | | The first year CE being "1" resulting in the new millennium | starting at 2001 instead of 2000 also seemed idiotic, and | the 1900s being referred to as "the 20th century" was | something I always had to consciously compensate for. | Numbering items starting at zero would have given us more | elegant/less confusing ways to communicate those things. | | Zero-based indexing makes things inherently simpler because | it matches the way we write numbers (and becomes much more | noticeable once you have more than one digit). It's not | just an optimization for computers. | adolph wrote: | Well, given that year numbering system's start in Europe, | zero wasn't as broadly accepted as other digits at the | time. | | _By AD 150, Ptolemy, influenced by Hipparchus and the | Babylonians, was using a symbol for zero._ | | https://en.wikipedia.org/wiki/0#History | | To keep it confusing: _the traditional proleptic | Gregorian calendar (like the Julian calendar) does not | have a year 0 and instead uses the ordinal numbers 1, 2, | ... both for years AD and BC. Thus the traditional time | line is 2 BC, 1 BC, AD 1, and AD 2. ISO 8601 uses | astronomical year numbering which includes a year 0 and | negative numbers before it. Thus the ISO 8601 time line | is -0001, 0000, 0001, and 0002._ | | https://en.wikipedia.org/wiki/Gregorian_calendar#Dual_dat | ing | marak830 wrote: | I asked my son to show me zero fingers(after show me 2 | fingers and 5 fingers), he closed his fists. | anigbrowl wrote: | My point exactly - there isn't an identifiable zeroth | finger. | colonwqbang wrote: | There's not a second finger either. You can convey "two" | by showing any two fingers. | gitonthescene wrote: | And? My solution? Let the kid grow up and learn. | anigbrowl wrote: | pygy_ wrote: | Anecdotally, I taught my children numbers starting from | zero with a similar routine, based on cardinality. They | immediately got it. | | My kids' school also uses zero-based tables. | | "Natural" is a very loaded and ambiguous term, best | avoided if you hope to have sane discussions. | [deleted] | [deleted] | twobitshifter wrote: | Someone linked to your johnny decimal system earlier today. | https://johnnydecimal.com/ I liked the idea but I noticed that | it didn't seem to be 0 indexed. If I adopt this i'm definitely | going for zero indexing. | woojoo666 wrote: | I like how the article summarizes this idea: | | > These all point to one reason why 0-indexing might be | preferred: it matches machine semantics more | kergonath wrote: | But then of course the reason why 1-indexing is better (or | really, arbitrary indexing, which is even better) is that it | matches human semantics better. | jbaczuk wrote: | Yeah, but then couldn't the compiler just swap the 1 with a 0 | and 256 with 255? | kshacker wrote: | I can understand the rationale for 0 and 1. I can even understand | the rationale for a arbitrary range (from -5 to +10) in current | era where languages have iterated for many generations. | | However I did not understand why they would have a range in the | early days of programming. On one hand it would have been hard to | make a language and its compilers and then you add arbitrary | ranges? | aaaaaaaaaaab wrote: | Early programmers were mostly mathematicians and physicists, so | the notation borrowed a lot from their fields, where it's | common to index sequences with arbitrary numbers. And it's not | particularly complicated to implement either. | anigbrowl wrote: | _I may think that counting 0 as a natural number makes a lot of | math more elegant, but clearly I'm just too dumb to rise to the | level of wrong._ fruits = ['apple'] \\ Hello I | have fruits x = len(fruits) \\ Only one kind tho lol | fruits[x] \\ OK here is what I have SUBSCRIPT | OUT OF RANGE | | I have always hated zero indexing for this reason (other than | thinking in assembler where it is beautiful). It is of course | useful in many contexts, albeit with tradeoffs; more importantly | everyone is used to it and it's predictable. But I was absolutely | thrilled to discover Julia defaults to indexing from 1 like a | normal person. | | Essentially what we have here is a mismatch between the tool | (computer that does everything in binary) and the task | (mathematical abstraction of quantities). Now it's completely | understandable that people work within the limitations of the | tool when there is no other choice, but that's the same sort of | path dependency that creates technical debt. | | If zero indexing were so great, mathematicians would have made it | the default centuries if not millennia ago; but mathematicians | don't want to do off-by-1 adjustments on all sorts of common | operations because it makes things unnecessarily complicated. To | be honest, I think this has become a moat to keep people out of | programming even though it's a shallow one. | | It could be interesting to test this, say by taking two classes | of schoolchildren and teaching one Julia and the other Python | (or...). By not having to take on the idea of zero-indexing at | the same time as the concept of an array, the Julia group can get | into collections using their intuitive understanding of the | natural numbers. I expect that picking up language elements | quickly will have a compounding effect and that at the end of the | evaluation period the Julia group will be able to make | significantly more complex programs than a control group. | | Edit: in your heart you know I'm right | waynecochran wrote: | It's an offset from the beginning. Simple as that. | 323 wrote: | Obligatory, there are a lot of memes on this subject: | | https://www.google.com/search?q=arrays+start+at+zero+meme&tb... | make3 wrote: | I always assumed that it was because arrays and pointers would've | been interchangeable in the start, and that adding a zero index | times the object size gives you the first element | twanvl wrote: | Other advantages of zero based indexing, beyond being 'closer to | the machine': | | It works better with the modulo operator: `array[i%length]` vs | `array[(i+length-1)%length+1]`. Or you would have to define a | modulo-like operator that maps N to [1..n]. | | It works better if you have a multi-dimensional index, for | example the pixels in an image. With 0 based indexing, pixel | `(x,y)` is at `array[x+width _y]`. With 1 based indexing it is at | `array[x+width_ (y-1)]`. You might argue that programming | languages should support multi-dimensional arrays, but you still | need operations like resizing, views, etc. | tabtab wrote: | In many domains code maintenance is more important than | hardware costs. In many domains 1-based indexing is a better | fit, meaning less conversion code, meaning simpler code. Thus, | the best indexing choice depends on the domain and | circumstances, as do many controversial questions. Most tend to | specialize in specific kinds of domains and over-extrapolate | their experience into other domains. | wizofaus wrote: | I'd agree so why did languages that allow specifying the base | die (other than maybe VBA). | btilly wrote: | Because changing the base is a great source of bugs. | | That said, not all languages have given up on this. For | example Julia allows it. | https://docs.julialang.org/en/v1/devdocs/offset-arrays/ | | Ironically I learned this from a discussion of Julia bugs. | Apparently changing offsetting of arrays has proven to be a | source of bugs in Julia. So maybe someday they will come to | the same conclusion as languages like Perl and stop | allowing it. | wizofaus wrote: | I'd argue 0-base is a source of bugs too! Ideally we'd be | able to catch more array indexing bugs at compile time - | there are definitely cases where it should be possible to | determine that arrays are being incorrectly indexed via | static analysis. | btilly wrote: | The problem is that libraries which assume 0-base break | when you have a 1-based array. And vice versa. Trying to | combine libraries with different conventions becomes | impossible. | | Therefore changing the base leads to more bugs than | either base alone. | | That said, the more you can just use a foreach to not | worry about the index at all, the better. | | Of 0-based and 1-based, the only data point I have is a | side comment of Dijkstra's that the language Mesa allowed | both, and found that 0-based arrays lead to the fewest | bugs in practice. I'd love better data on that, but this | is a good reason to prefer 0-based. | | That said, I can work with either. But Python uses | 0-based and plpgsql uses 1-based. Switching back and | forth gets..annoying. | msdrigg wrote: | This is the reason I always think of when I hear the question | bluetomcat wrote: | A disadvantage comes to mind. While the following loop works as | expected: for (size_t i = 0; i < length; i++) | ... | | The following causes an unsigned integer underflow and is an | infinite loop: for (size_t i = length - 1; i | >= 0; i--) ... | operator-name wrote: | In that specific case I'd do the following: | for (size_t i = n; i-- > 0 ;) ... | | Or count from `length` to 1, but subtract 1 in the loop body, | or count up and subtract the length in the loop body. Any | modern compiler should be able to optimise these to be | equivalent. | | In the majority of cases, counting down is not necessarily. | Nor is ordered iteration. Most languages have a `for each` | style syntax that's preferable anyway. | divbzero wrote: | Or alternatively: size_t i = length; | while (i--) ... | cylon13 wrote: | Ah yes, the goes-to operator --> | tomjakubowski wrote: | And the wink operator, so the compiler knows you know the | deal | wizofaus wrote: | Gold - have an upvote! | pwdisswordfish9 wrote: | You can always rip a page out of C++'s playbook: | for (size_t i = length; i > 0; i--) { // ... | item = array[i - 1]; | | (This is how reverse iterators work in C++.) | mananaysiempre wrote: | As Jens Gustedt points out[1], the following _intentional_ | unsigned overflow works perfectly for downwards iteration | (even when length is 0 or SIZE_MAX), though it looks a bit | confusing at first: for (size_t i = length - | 1; i < length; i--) ... | | You are also free to start at any other (not necessarily in- | bounds) index, just like with ascending iteration. | | [1] https://gustedt.wordpress.com/2013/07/15/a-praise-of- | size_t-... | xxs wrote: | the footnote [1] should be [0], just for the sake of this | very topic. | | Seriously though, while the idiom does work for unsigned | integers, it's a bad idiom to learn [makes code reviews | harder]. The post-decrement one in the loop body works with | everything (signed/unsigned), and it's well known. | 411111111111111 wrote: | Uh I'm confused but don't know c++. | | why doesn't that loop end instantly? | | I mean length - 1 < length should always be true, right? | | Or does it only terminate when the number underflows? | Terribly confused here | msk-lywenn wrote: | It's a condition to run, not a condition to stop | wizofaus wrote: | That was my reaction - why should anyone think it might | be the latter? Are there languages that do have such a | syntax without explicit keywords ("do...until")? | bobthepanda wrote: | It's an unsigned int, so past 0 it overflows back to the | maximum | 411111111111111 wrote: | Ooh, i see. I wasn't aware that they under/overflow at 0 | when they're unsigned. Thanks for broadening my horizon! | billforsternz wrote: | The loop continues until i transitions from 0 to 0 minus | 1. 0-1 in this case actually doesn't equal -1 since | size_t is an unsigned type, instead it wraps around to be | the largest possible positive integer instead. TLDR; yes | as you speculate it terminates when the number | underflows. | naavis wrote: | It loops while the condition is true. When an underflow | happens, it stops being true. | Jtsummers wrote: | For loops are translatable from: | for(initialize; condition; increment) { ... } | | to: initialize; while(condition) { | ... increment } | | (more or less, some scoping things not encompassed by the | above; this is also how pretty much every for loop in a | C-syntax language works) The condition of a for loop is | equivalent to a while loop's condition. So yes, _length - | 1 < length_ will be true on the first iteration, which is | fine because the loop continues _as long as_ that | condition is true. | | What the above approach takes advantage of is that when | underflow eventually happens you'll have this condition: | MAXINT < length | | Which will terminate it for all possible values of | _length_. | salawat wrote: | Principle of least surprise violated. | | Also, that behavior is not guaranteed. The programmer would | need to be aware of how the particular machine in question | actually handles that. | | Then again, that's C. | sersnth wrote: | Unsigned integer underflow and overflow are both | guaranteed to wrap by the C standard. | nemetroid wrote: | Unless wrapping underflow is sensible for the domain (which | it isn't when representing the size of something), unsigned | integers are usually a bad idea. | [deleted] | ncmncm wrote: | If you have foolishly turned off -W in your build system, | that could happen. Otherwise, you get a nice warning pointing | out your folly. | 10000truths wrote: | for (size_t i = 0; i < length; i++) { size_t j = | (length - 1) - i; ... } | | EDIT: change i to j | yuliyp wrote: | That's quite broken (you'd want a different variable inside | the body, vs clobbering the iteration counter, else this | would process the last item in your list, then exit). | Banana699 wrote: | You should save the old value of i somewhere and restore it | back at the very end of the loop. Or simply define a new j | like another comment says. | unwind wrote: | Uh no don't reassign the loop variable in the inner scope. | Use: const j = (length - 1) - i; | | in that case. Much safer. | rabbidruster wrote: | I hope you haven't done this anywhere. | | Makes my brain hurt, but I think this will only run through | the loop one time looking at the last element of the array. | bregma wrote: | In the C programming language unsigned integers do not | overflow. They wrap. This is well-defined behaviour and the | example code is simply incorrect. Most modern compilers will | give you a diagnostic for this. | xxs wrote: | the correct way/idiom to reverse iterate an array is | for (size_t i = length; i-- > 0; )... | | It's surprising how often the issue pops, it works well with | both signed and unsigned integers. | | (edit) I've started with one based indexing (basic)... mixed | with 0 based (assembly), more 1 based (pascal), then more | stuff (all zero based). I am, yet, to see a real advantage of | a one based indexing... after the initial process. | empiricus wrote: | Is this cache friendly? | msk-lywenn wrote: | It's not. It was nice on architectures were cache didn't | matter much and were subtracting and comparing to zero | was just one instruction (looking at you old core ARM) | sgtnoodle wrote: | Sure, why wouldn't it be? As far as a cache is concerned, | I don't think reverse sequential iteration would be any | different than forward sequential. The actual RAM | accesses may be less optimal if there's some speculative | pre-fetching with assumed forward sequential access, but | that's conjecture. | youor wrote: | mananaysiempre wrote: | A rare case where 1-based indexing is more convenient is | complete binary trees laid out breadth-first (as in a standard | binary heap): parent is i div 2 and children are 2i and 2i+1 | when starting at one and who knows what when starting at zero. | But that's the only one I know. | btilly wrote: | With 0-based indexing the children are at 2i+1 and 2i+2. The | parent is at (i-1) div 2. | | Not hard to figure out. | JadeNB wrote: | > With 0-based indexing the children are at 2i+1 and 2i+2. | The parent is at (i-1) div 2. | | > Not hard to figure out. | | While that's true, "you just shift by 1" is equally good at | all arguments for or against 0-based indexing, so deploying | it here probably won't convince. | btilly wrote: | I was not trying to convince. | | That said, the effort of one versus the other is so | trivial that there is no point in ever using effort as an | argument either way. Doubly so because what seems like | effort to us is simple unfamiliarity. | | What _is_ important is which one leads to more careless | errors in practice. As a trivial example, consistent | indentation takes effort, but failing to do it leads to | more careless errors. Therefore everyone indents code. | | The only data point I've seen on that is the side remark | about Mesa in https://www.cs.utexas.edu/users/EWD/transcr | iptions/EWD08xx/E.... That remark, therefore, is the only | argument that I care about. | wizofaus wrote: | Except 1-based indexing is what we use in normal language. We | don't use "zeroeth" or "player (number) zero" etc. And the | word "first" is shortened to 1st etc. Personally I think we'd | be better off if programming languages stuck to the same | convention - off-by-1 errors aren't the hardest problems to | deal with but they're still annoying. | misttar wrote: | The 2 major blunders in programming: 1) Off by one errors. | ChickeNES wrote: | Well: https://www.merriam-webster.com/dictionary/zeroth | OscarCunningham wrote: | I think the 1-indexing folks would have to argue that a%b | should return a value from 1 to b inclusive. This does make the | same sort of intuitive sense as 1-indexing. For example we | number clocks from 1 to 12. | black_knight wrote: | But interestingly, the number at the top is 12, not 1. | cryptonector wrote: | 12 is zero, in 12-hour clocks. | vore wrote: | % is defined as (mostly) a remainder operator. I don't think | you want to change the semantics of division itself. | OscarCunningham wrote: | Right. Ultimately the 1-indexers are wrong. | ur-whale wrote: | Unfortunate that the Julia folks weren't exposed to this when | they designed the language. | Jtsummers wrote: | https://juliaarrays.github.io/OffsetArrays.jl/stable/ | | 0-based or any arbitrary offset of your choice so that your | data model can more closely map to what you need it to. And use | _eachindex_ instead of making assumptions and you can work with | arrays using 1-based, 0-based, or arbitrary-based indexing. | chmod775 wrote: | Another reason can be performance/memory. | | When you index starting at 1, you either have to add/subtract 1 | internally, which sometimes but not always can be optimized away | by a smart JIT/compiler, or you have to "waste" the first element | in memory, trading memory for performance. | | Lua always subtracts 1, while LuaJIT instead went with the latter | approach. | Gordonjcp wrote: | Because memory starts at zero, because the lowest address you can | select in memory has all its address lines set to zero. | | If you don't understand this, you should not be writing computer | software. | Grustaf wrote: | Simple: because we start with index 0 in mathematics. | auggierose wrote: | Funny, just a few hours ago I asked myself the related question | "Should indices start with 0 or 1?" (not for the first time). I | pretty much switch my opinion as many times as I think about it. | | Here is a nice discussion on stackoverflow | https://cseducators.stackexchange.com/questions/5023/why-do-... | | The first answer nicely retells the dijkstra argument: integer | ranges should be described using _half open intervals_ , and [n, | m) is nicer than (n, m]. Furthermore, [0, n) is nicer than [1, | n+1), and that's that. | | The second answer makes the observation that there is a | difference between _indexing_ and _counting_ , and that even in | daily life often the first element is indexed by 0. | | Still, I rather like indexing the first element of a sequence | with 1. | glitchc wrote: | Array indices denote offsets from the base address. The first | element is at the base address of the array, hence the offset is | zero. It avoids a conditional when resolving the address, | introducing it would slow down all forms of memory access across | the language domain. | goatlover wrote: | Yet somehow Fortran manages to be highly performant. | oh_my_goodness wrote: | "math [...] sums seem to always be 0-indexed," | | What? Is this some kind of trolling challenge? If you don't care | about math, just say so. Most people don't. But making up a | nonexistent convention is just silly. | snarfy wrote: | Indexes start at 1. Offsets start at 0. | | Arrays in programming use offsets. for(int | i=0;i<10;i++) { array[i] = x; } | | The error here is calling it 'i' for index. It should be 'o' for | offset. | nomel wrote: | Arrays in the programming languages you're familiar with use | offsets. | | Not all do [1]. | | 1. https://therenegadecoder.com/code/which-programming- | language... | snarfy wrote: | Of course, and I've used Lua for a long time. | | The point is that offsets and indexes have different meaning. | anamexis wrote: | Where are you getting this definition of index? | tunesmith wrote: | I always assumed it came back to math, and that t0 or time-zero | is useful for the beginning state _before_ anything happens. | goatlover wrote: | What if there was no t0 for the universe, as Hawking and a few | other physicists have argued? There was just the first plank | second and no meaningful before. | notpushkin wrote: | The _Lessons_ section is brilliant. | tejtm wrote: | For me it comes down to; are you enumerating intervals or items | to offset into. | caxco93 wrote: | I always thought it was because it's easier multiplying the index | by the size of the array item to get the correct offset | labrador wrote: | Because zero is a concept that can mean "at the beginning" | | _The symbol changed over time as positional notation (for which | zero was crucial), made its way to the Babylonian empire and from | there to India, via the Greeks (in whose own culture zero made a | late and only occasional appearance; the Romans had no trace of | it at all)_ | | Another meaning is "nothing" but we're talking about position, | not nothingness | | _The mathematical zero and the philosophical notion of | nothingness are related but are not the same. Nothingness plays a | central role very early on in Indian thought (there called | sunya), and we find speculation in virtually all cosmogonical | myths about what must have preceded the world 's creation. So in | the Bible's book of Genesis (1:2): "And the earth was without | form, and void."_ | | https://www.scientificamerican.com/article/what-is-the-origi... | ur-whale wrote: | So that modulo works the way god intended inside a ring buffer. | franciscop wrote: | I've discussed this a lot in real world in a different field: | apartment floors. In Japan (where I live) they are 1-indexed, | where the floor on the ground is number 1, while in Spain (where | I am from) they are 0-indexed, where the floor on the ground is | number 0. | | Both have inconsistencies, like in Spain you might have a "middle | ground" (entresuelo) which is neither 0 nor 1, but sits between, | and is normally commercial or non-livable, reserving the 1 to the | first floor where people live. I like that system better though | because it usually goes 1 => 0 => -1 (underground), while in | Japan you go 2 => 1 => -1, so I feel like it's missing a floor. | You could justify it though as 0 being the ground line, so +1 is | "the first above the floor and -1 is "the first below the floor", | but I still prefer having each floor to be a natural consecutive | number. | andy81 wrote: | English also has that "mezzanine" concept, for partial floors | with a balcony over the main floor. You see it sometimes on | elevators as an M. | onlyrealcuzzo wrote: | It seems like most newer buildings in the US and EU have "G" or | "L" be the ground floor (0 / PB), and then the floor above is | "1". | | In older buildings, the ground floor is usually "1" - which | means the floor above has to be "2". | user3939382 wrote: | I (US) don't remember seeing the second floor labeled 1. I | often see G, 2, 3 | jschveibinz wrote: | I have always assumed that is just one less operation required to | resolve the absolute memory address. | nsajko wrote: | No. | | 1. Optimizing compilers exist. | | 2. Addressing at fixed offsets is cheap (a single instruction): | https://en.wikipedia.org/wiki/Addressing_mode | | 0-based indexing is superior (as a default) because it | simplifies a lot of common math, as discussed in TFA. | mjevans wrote: | 3. Less buggy for small systems since the Base Pointer | address points directly to a record. | | 4. Macro expansion is often used to store indexes and other | 'magic numbers' in Assembler, and this pattern originated | either when Assembly was the primary programming language, or | even earlier when humans directly punched out cards with | machine instructions. Compilers in any remote sense of the | luxury we have today did not exist or were not common. | espadrine wrote: | That is true for vectors, but not matrices, right? | char at(char matrix[10][10], char i, char j) { return | matrix[i][j]; } | | still has more computation on 1-indexed than on 0-indexed, I | believe. | contravariant wrote: | Well you've either got: | | memory_address + array_width*i + j | | or | | memory_address + array_width*(i-1) + (j-1) = | (memory_address-array_width-1)+ array_width*i + j | | so you can just absorb the extra computation into the | pointer. | auggierose wrote: | TFA = Thanks For Asking? | brobinson wrote: | The "Friendly" Article | layer8 wrote: | https://mtsknn.fi/blog/tfa-stands-for-the-featured-article/ | goatlover wrote: | > 0-based indexing is superior (as a default) because it | simplifies a lot of common math, as discussed in TFA. | | If that was true, Fortran, Julia, R and Matlab would use 0 | instead of 1-based. | bee_rider wrote: | The mental model of being an offset to a memory address is, I | think, part of it. | | I'd be surprised if the use of zero vs one actually made any | difference, from a number of operations point of view -- from | the compiler's point of view, the first element in the array is | the first element in the array, no matter what we call it. | | I mean in an extreme edge case maybe if you are computing an | index, and it happens to be zero, then in your math maybe some | identity related to zero could be exploited (go to element | simple_integer*complicated_function(), where simple_number | might be zero) but that seems a bit silly. | Yujf wrote: | How would it not make a difference? If you calculate an index | at runtime, to get access to the element, in 0 based would be | pointer + index. In 1 based it is however pointer + index - 1 | clearly there is an extra subtraction there? | | In x86 you could probably hide it in the addressing but that | does not mean it does not to be computed | goatlover wrote: | If you're calculating indexes at runtime, you're probably | not worried about that level of optimization. | rhacker wrote: | This is primarily the actual answer. While most languages force | you to see the array as an array, in C/C++ (in C++ I'm only | referring to the memory allocated variable type, not an "array | class") you can see it as a pointer and do your own math to | address any part of it that you want. And the calculation for | that memory address is idx * sizeof(the thing in your array). | So the real answer here is that array semantics needed to match | memory address semantics in the languages that provide that. | copperx wrote: | There's no reason why memory addresses had to start at 0. | [deleted] | unixbane wrote: | So what's the actual reason you'd want to have zero based arrays | and such in your language (In 2020, not 1970)? In a language from | scratch that doesn't care about being like previous ones, and | doesn't care about micro optimization. | | I've been annoyed recently by this obnoxious neckbeard behavior | when they make things zero based for no reason (other than to | conform to their supposedly existent philosophy), like Ratpoison | and Screen selecting windows by a zero based index, which means | you have to move your hand to the far right of the keyboard to | select the _first_ window with the 0 key, the far left to select | the _second_ window, with the 1 key, and one to the right to | select the _third_ window, with the 2 key. | | I so happen to have been trying to work out a tangible | explanation on paper of which system is better on trips a few | weeks ago, and could not come up with one (and none are given in | the article nor the top comments in this thread). | | On a side note, the moment you say, "zeroeth", you can no longer | be sure anyone knows what you're talking about because at any | moment you may count in English or this pretentious UN*Xtard | dialect of English. Seems like another pedagogical stumbling | block held on to boomers and boomer-wannabes who just want to | have their little counter counter counter culture or whatever. | juped wrote: | Zero-based _indexing_ is always wrong; an ordered collection of | things does not have a zeroth thing. | | Sometimes you have a data structure called an "array", which | means "a bunch of things that are the same size next to each | other in memory". You can store the address of the whole array as | the address of its first element, and offset into it by an | offset; clearly, the offset of the first element is zero, but | it's not the "zeroth" element. | | And finally, sometimes you have cargo cult behavior by people who | think that the way offsets into arrays work is because "numbering | starts at zero in computers!" or some similarly wrong | rationalization. This is when you get stupid things like (nth 0 | list) in a lisp. | kazinator wrote: | Some guitars have a zeroth fret; an actual fret at the nut. | dalmo3 wrote: | An ordered collection of events in time usually starts at t(0). | ryanisnan wrote: | I hate to break it to you but natural spoken language is not a | fixed concept, words can have many meanings and | interpretations, and those meanings and interpretations can | mean different things to different people at different times. | | Because you predominantly think of indexing as the first | definition as shown here[1], does not mean everyone else does. | Be careful when using absolutes, especially when talking about | languages. | | [1] - https://www.merriam-webster.com/dictionary/index | Schroedingersat wrote: | An ordered collection of things starts no things from the | beginning. | | A journey starts 0 metres from the origin. | | If you count the number of _ you are along your journey and | start with 1, then at the second metre you are at the 101st | centimetre. | | When someone says how many dragons have you slain? Just as you | leave and haven't heard of any dragons yet, you don't say "I'm | slaying my first dragon now" | | Every construction of the natural numbers I have seen starts | with 0. | | The first hour of the day has passed when the clock strikes | one. The hour preceding that is the same day. English calls it | 12 because it was invented before we had a firm grasp of zero | and english is inconsistent. 24 hour clocks call it 00. | | 1 based indexing can be correct, but 1 based ordered discrete | sets map incredibly poorly to any ordered set with a different | number of elements (such as the reals). Additionally dealing | with ranges is less easy to make consistent. | | 0 based indexing is always correct. | calibas wrote: | The index of an array is an integer, and integer values start at | zero, so it seems like an obvious choice as to where the starting | point should be. It's only outside of computer science that it | seems to be counter-intuitive. | xg15 wrote: | I don't quite understand the argument "0-based being easier for | pointer arithmetic is nonsense because the language doesn't have | pointers". | | Whether or not the language presents the concept of "pointer" to | the user is independent of whether or not it uses pointers | internally. And if it exposes arrays as a concept, it has to | implement them somehow. | | The simplest possible implementation of arrays is having a start | address and putting all elements next to each other in RAM. To | get the address of a particular item, this layout naturally leads | to the formula "base address + index * element size", with | "index" being 0-based. If you want to expose other indexing | schemes in your language, you'll have to add more logic to | convert the user-visible index back to 0-based before you can | obtain the address. | | All of this is completely independent of the fact whether your | language exposes pointers to the user or not. | | Even the yacht story sort of hints at this: | | > _To keep people from having their jobs cut short by yacht- | racing, Richards designed the language to compile as fast as | possible. One optimization was setting arrays to start at 0._ | | If all indexing schemes were equal, why would this change even be | an optimisation in the first place? | turboponyy wrote: | Nats start at 0, end of discussion - it's only logical to index | by the naturals. | salty_biscuits wrote: | Where 0 is the cardinality of the empty set, i.e. some empty | collection. Not a convincing argument. | JadeNB wrote: | > Where 0 is the cardinality of the empty set, i.e. some | empty collection. Not a convincing argument. | | Why not? "Every cardinality, _except of the empty set_ , is | a natural number" isn't very convincing to me, if we're | making cardinal-based arguments. | salty_biscuits wrote: | I'm not arguing that the natural numbers should start | from one, rather that the usual path for developing the | natural numbers starting with set theory is that zero is | the size of a set with nothing in it. In maths they | always talk about the first element in a vector, not the | zeroth. It is a bad argument to point to mathematics for | using zero based indices. It is not at all common to use | zero based indexing there. | thaumasiotes wrote: | It's not a convincing argument because you index into an | array if you want to retrieve an element contained in the | array. If 0 is the cardinality of an empty collection, | it's not a valid index, because you can only index into | non-empty collections. | mtizim wrote: | That's really silly - the natural numbers also famously start | at either 0 or 1, depending on the country, the discipline, | and the individual. | zzo38computer wrote: | It is because you mean two different things by "natural | numbers", even though the same words are used for things | that are not the same things. | | I prefer to start by zero; I think it is more useful in | general, and makes more sense mathematically for many | (although not all) purposes, and systems that you will find | objects and operations that have these properties too. | thaumasiotes wrote: | I like to treat the naturals as starting at zero, but not | for any mathematical reason. I just think that since it's | easy to write Z+, it's more useful for N to refer to | something slightly different than it would be for N to be a | synonym for Z+ while anyone wanting to include zero in | their set was forced to spell out "nonnegative integers". | | A dichotomy between "Z+" on the one hand versus "N" on the | other is just plain _more convenient_ than a dichotomy | between "Z+" and "N" on the one hand versus "Z\Z-" on the | other. | JadeNB wrote: | > Nats start at 0, end of discussion - it's only logical to | index by the naturals. | | Now you'll just bring out the people who start the naturals | at 1. | ajg36 wrote: | Starting the naturals at 1 is quite onerous. | thaumasiotes wrote: | > Nats start at 0, end of discussion - it's only logical to | index by the naturals. | | Well, no, obviously you want to index by ordinals, and they | start at "first". | topaz0 wrote: | If there were any justice in the world, they'd start at 2, as | a handicap. They might even make it out of the bottom of the | NL east if that was the case. | Someone wrote: | > To get the address of a particular item, this layout | naturally leads to the formula "base address + index * element | size", with "index" being 0-based. If you want to expose other | indexing schemes in your language, you'll have to add more | logic to convert the user-visible index back to 0-based before | you can obtain the address. | | The easy way to do that is by shifting the base address. In | pseudo-C (I think that computing the _b_ pointer is non- | conforming, even if the code never tries to access _b[0]_ , but | compilers can do this without problems): int | a[100]; // array of 100 integers, zero-based int * | b = a - 1; // array of 100 integers, one-based | | Things only get costly when you want to check array bounds or | when you have multi-dimensional arrays. There also may be non- | standard architectures where this kind of stuff isn't possible. | twobitshifter wrote: | Should work 99.99999% of the time until someone tries to put | an array at 0x000001 :) | alexcosan wrote: | I think, in theory, it would work regardless of the | starting address. As long as you don't try to access the | invalid address (which you wouldn't assuming that it's | starting in the index 1, you would always be accessing the | first valid address) | [deleted] | matthewmcg wrote: | Amusing but probably irrelevant: the sailing yacht racing | handicapping calculations mentioned are almost certainly under | the Performance Handicap Racing Fleet (PHRF) system[0]. This | system is "zero based" in its own way. A sailboat's performance | is assessed and handicapped against a standard yacht with a | zero rating. Your time to complete the race course is adjusted | by your handicap to determine your final standing. This lets | you race slower and faster types of boats in a "fair" way. | | [0] https://en.wikipedia.org/wiki/Performance_Handicap_Racing_F | l.... | blueflow wrote: | That so people in this thread argue about the higher-level | language (missing the point) shows that few people found access | to the underlying machine code. | | Which is sad, because all code is still executed as machine | instructions even when the developer does not see it or does | not want to care. | gitonthescene wrote: | It was just most basic example. Indices are connected with | math all the time. Consider implementing circular queues with | 1-based arrays. Any arguments about what's _possible_ miss | the point. Arguments about what _feels_ natural purport to | know the human mind which I find generally suspect. Mostly I | think of computers as tools and am interested in getting the | most functionality out as smoothly as possible not as slaves | whose job it is to make my life worry free. | Blikkentrekker wrote: | "machine code" isn't really the zero point that's special | nowadays. | | The code the programmer wrote is compiled to something such | as LLVM IR, LLVM IR is further compiled by LLVM to Assembly, | this is further compiled by an assembler into machine code, | and then the c.p.u. further compiles this to it's internal | code as it executes it. "machine code" really is no more | special in this chain of events than, say, LLVM IR. | blueflow wrote: | Machine code is special because its the only thing the CPU | can actually execute. | [deleted] | just_boost_it wrote: | We're 20 years past the point where you can expect everyone | in tech to trace every instruction down to machine | instructions. Higher level languages abstract away the need | for it, and for the most part, we can rely on the authors of | those languages to make many of the decisions that impact | performance. The rest of us learn about these details on | posts like this. It's not a sad fact, in fact it's probably | one of the most useful things that's happened in tech. It | frees people to think about other problems. | ryanbrunner wrote: | If you're not raining about how your code translates to | logic gates, you're not a competent programmer. /s | | Abstractions are good, and while we should be careful not | to completely trust a brand new abstraction, high level | languages are established enough that we don't need to | worry about it. | ivanhoe wrote: | 20 years ago ASM was just as cryptical black magic to most | of programers as it is today... try perhaps 40 y/a... | metafunctor wrote: | Not sure if you were around 20 years ago, but you sure | couldn't expect everyone in tech to understand machine | instructions as well as the layers above, all the way up to | corporate politics. | | But some people, yeah, they could do it. | | That has not changed. | [deleted] | TillE wrote: | I barely touch assembly in my day to day work, but I do | understand on a fairly deep level _how a computer works_ , | which I feel is extremely important and very frequently | influences how I write high-level code. | | Certainly one _can_ bang out code their entire career | without ever having a clue how machine code works, but I | really wouldn 't advise it. At worst it leads to total | ignorance, and at best you accumulate a disconnected set of | "best practices" as inscrutable lore handed down from on | high. | tdeck wrote: | If this were the primary reason, it seems odd that some of | the earliest popular languages used 1-based indexing in an | era with much slower CPUs (<= 1 MIPS) and less available | memory to store instruction code. If the authors of FORTRAN | were comfortable with 1-indexing on the IBM 704 (40 KIPS) in | 1957, it couldn't have been prohibitive. At the same time, as | computer use cases became more interactive there may have | been a greater focus on performance, but it likely that the | semantics of the high-level language were at least as | important. | iib wrote: | 0 for offsets, 1 for ordinals, that's usually the rule. Of | course, both are conventions. | lupire wrote: | Implementation matters for performance, but even beyond that, | the interface matters for users. 0-based offsets are convenient | for users doing math on indexes. | | A pointer is just one kind of array-like indexing scheme. Good | pointery languages will distinguish Address from Offset from | Integer. | bluetomcat wrote: | The "language" that has a 0-based indexing scheme is assembly. | An HLL with 1-based counting that compiles to assembly will | introduce additional computational overhead for the translation | of the index. | | If 1-based indexing was used in assembly, then "mov | 1(%ebx),%eax" would be the equivalent of "mov (%ebx),%eax". | unilynx wrote: | Not sure if assembly/machine code is that relevant. If one | based indexing was more prevalent, the LEA instruction on x86 | would just subtract one during execution | dboreham wrote: | "just subtract one" would take a long time 50-60 years ago. | Jtsummers wrote: | If you did this, you'd subtract one _once_ at array | creation. Or subtract whatever the offset is (really, you | 'd subtract 1 * data type size). Under the hood, using C | syntax instead of assembly: int foo[n]; | // what the user wrote // what happens behind | the scenes, after a fashion int* foo = malloc(n * | sizeof(int); // or sp - n * sizeof(int) if stack | allocated; subtraction since stacks usually grow "down" | foo = foo - 1; | | All references into _foo_ will now work just fine so long | as they are within the [1,n] range (same issues as with | 0-based there since C doesn 't carry size information for | checking array bounds access). This adds one extra | instruction per allocation (which includes allocation on | the stack) for all non-0 offsets, but then all access | will have the same cost whether 0-based, 1-based, or | arbitrary-based. That's a non-zero cost, but it's not | exorbitant since you'll be accessing much more often than | allocating (and if it's reversed, something weird is | happening). | kitkat_new wrote: | would it? or would it be just a differently wired | circuit? | cryptonector wrote: | u/blutomcat's point clearly (I think) was that instruction | sets didn't do what you suggest, so zero-based index is | (was and still is) what you'd do if you wrote in assembly | (which was not uncommon!), and on any given platform, | assembly was _the_ main language 50-60 years ago. It | follows that it 's easier to carry that over to higher | level programming languages. | | Whether that's what actually happened in the cases of HLLs | that adopted zero-based arrays or not, I don't know. But | today, to me, zero-based array indexing feels very natural, | and the idea that zero-based arrays being simpler in | assembly carrying over to HLLs seems at the very least | plausible. | jiveturkey wrote: | > additional computational overhead | | at compile time, not runtime. | saalweachter wrote: | For constant addressing; for arr[i] = 2, you'll still need | to subtract 1 from i with 1-based addressing when | converting to machine instructions. | [deleted] | vukgr wrote: | Can't say I've really thought this through, but couldn't | you just subtract 1 (*sizeof(X)) from the arr address? | saalweachter wrote: | Hmm, maybe? | | You'd still have the odd subtract here or there, but for | many use patterns you could probably ignore the overhead. | tremon wrote: | What would memset(arr, 0, sizeof(arr)) do in that case? I | can see myriad problems with having arr itself point | outside the memory range allocated to arr[min..max]. | Uptrenda wrote: | This is far easier and clearer than the entire article. Good | stuff. | vbezhenar wrote: | Waste 0th element or reuse it for something like length (hello, | pascal strings). Another option is using base_address - | element_size as your array value. Another option is using | +element_size for all array accesses, assembly languages | usually have this instruction. There're many options to use | 1-based indexing without sacrificing performance. | xg15 wrote: | > _assembly languages usually have this instruction_ | | Is that so? I wasn't aware of that. | vbezhenar wrote: | At least x86_64 can put something like `ptr[index * 4 + 4]` | in one instruction (assuming that variable values are in | registers). Not completely sure about ARM. | ottoflux wrote: | my thought is just "why not"? | | 0 is a number, and just because the west ignored it for quite | some time (read: "Zero: The Biography of a Dangerous Idea") we | have these odd built-in aversions to it but in the end it makes | plenty of sense. | | 0th element is 0, so why don't we just do a better job of | educating kids to start counting with 0 and thinking about 0. | | in the end - as a CS person, i think it's good - but i also don't | mind if you disagree with me. :) | mirekrusin wrote: | Almost as interesting as hearing arguments for/against | tabs/spaces. | soheil wrote: | The concept of nothing doesn't really belong in the number line. | It's like inventing a new "number" to represent blue and then | using it instead of pi. | dhosek wrote: | When he talked about BASIC having 1-based arrays, I had to check | my memory against online AppleSoft BASIC documentation and | indeed, AppleSoft, at least did have 0-based arrays.1 I also had | to check on Pascal which I haven't written anything significant | in for some 20 years and it turns out that by default, Pascal | arrays are 1-based, but most of the code that I worked with | (which tended to have its roots in Knuth-written Pascal) | explicitly specified the range of indices. | | [?] | | 1. As did all the other contemporaneous BASICs that I | encountered. For added fun, when creating an array with DIM, you | gave the highest index and not the number of elements so, e.g., | DIM A(20) created a 21-element array. The 1980 Apple ][ manual I | found which discusses both Integer BASIC and AppleSoft doesn't | admit that 0 is a valid index for an array, but elsewhere I saw | it indicated as such which leads me to suspect that Integer BASIC | has 1-based arrays. | wizofaus wrote: | Modern Basic (VBA etc.) still supports 1 based arrays, and | there's even Option Base (0|1). This is a global directive for | all arrays declared in the same file. And individual arrays can | be declared with any starting index you like. | bitwize wrote: | Most of the BASICs I remember had 0-based indexing by default. | But you could change this with the statement OPTION BASE 1 at | the top of your program. | | This was true of even TI-99/4A BASIC, which was closer to | Dartmouth BASIC and not written by Microsoft. | phaedryx wrote: | If it starts at zero we should call it an "offset" | | That would fix so many of these discussions. | rcoveson wrote: | Maybe, but then they'd just become discussions about whether | `y` in the `x[y]` syntax "should" be an offset or an index. | Which one gets the language priority? | | ...Of course, the answer is offset, because offsets are | beautiful, composable, elegant things that harmonize with | bitmasks, modulo, array slices, and everything else, while | (one-based) indexes are nothing but "offset plus one", no more | useful than "offset plus two". | korse wrote: | base^0 = 1 base^1 = base base^2 = base * base et cetera. | | I've always considered the index and the power to which a base | has been raised to be equivalent in many circumstances. | | Thus starting at 0 makes sense. | asimpletune wrote: | In English, the day of your birth, when you're 0, is also your | birthday. So, technically speaking, when you're turning 29, | you're having your 30th birthday, even though no-one says it like | that. I always assumed 0-based indexing was something like that, | similar to the example given about the ground floor being the 0th | floor in some countries and the first floor in others. | | Another example is if I'm getting directions from someone, and | they say, "Walk 3 blocks that way", in my mind I conceptualize | that I'm presently on the 0th block and I don't yet count it. | | I don't think every day people disagree with these examples so | much (well, maybe the birthday one, but that's because we use the | same word for the literal day as well as anniversary), and | they're all fairly intuitive. I never realized that 0-based | indexing required such a deep background to be justified. | kbenson wrote: | > In English, the day of your birth, when you're 0, is also | your birthday. | | That depends on whether you think of "birthday" as synonymous | with "the actual day of my birth" or "a celebration of the day | of my birth". I think most of us actual consider it the latter, | which is why the first one is after you've been born for a | year. If you look up the definition of "birthday" (one word, no | spaces) you'll see that there is often some acknowledgement of | this in the differing definitions offered. | | > "Walk 3 blocks that way", in my mind I conceptualize that I'm | presently on the 0th block and I don't yet count it. | | You have to decide whether the person is saying something is on | the third block from your position, or you need to walk about | three blocks of distance. You probably do this automatically | based on how close you are to the edge of the current block. If | I'm 30 feet from the edge of a black, I'm probably not going to | include the current block in that distance. I imagine you | probably won't as well. | | > they're all fairly intuitive. I never realized that 0-based | indexing required such a deep background to be justified. | | I think they're only intuitive because we're all context | sensitive. The issue is when people don't have the same | context, or the context no longer strictly makes sense when the | terminology is used in contexts that make less sense. | | As an _offset_ , and in programming languages where it's easy | to see it's an offset (C), it makes perfect sense. In languages | where that's all hidden from you, and you're really just | referencing the nth item in a list, the 0th item doesn't make a | lot of sense. People in these different contexts will likely | have different ideas of what "intuitive" means with regards to | this. ___________________________________________________________________ (page generated 2022-08-24 23:00 UTC)