5 ms·
Zero based arrays are frequently better in a numerical context. Many times when you’re using the index in the computation itself (FFTs for instance), zero base
by civility 8y ago
Zero based arrays are frequently better in a numerical context. Many times when you’re using the index in the computation itself (FFTs for instance), zero based is what you want. For instance, the zeroth frequency (DC) is in the zeroth bin.
- KenoFischer 8y agoWhich is why julia doesn't make any assumptions on how your axes are indexed. If you're working in a numerical domain where 0-indexed arrays, or symmetric arrays about the origin, or arbitrarily other transformed axes make sense, just use those.
- civility 8y agoI understand the argument, but when the default disagrees with your override, there's almost always an impedance mismatch and some pain. It's like being left handed when 99% of the interfaces in the world assume you're right handed. People argue that zero-based is incidental, and that 1-based is the right way because of it's long history in mathematics notation. I would argue that 1-based is incidental, and that zero-based is better most of the time for modern math and computer architectures.
- KenoFischer 8y agoI can understand why you might get the impression, but I'd encourage you to try out julia and see that we're really quite good at using index-agnostic abstractions, so most code doesn't care what your arrays are indexed with. If a certain set of indices make sense in your domain (0-based for FFTs as you say, symmetric indices about the original for image filters, 1-based for just regular lists of things, etc), just use it, and it'll be convenient interactively, but most library code doesn't really think about it that much.
- civility 8y agoI'll (cautiously) take your word that this works transparently when I supply arrays as arguments to a library function. However, what does the library function return to me as arrays it allocates? What if I do an outer product of two arrays with different base indices? Whatever your answer, I suspect it is more cognitive overhead to remember than "always 1 based" or "always 0 based".
- KenoFischer 8y ago> However, what does the library function return to me as arrays it allocates? Depends what the library function does of course. If it's shape preserving (e.g. if it's a map over the array), it'll generally preserve the axes of the input array. > What if I do an outer product of two arrays with different base indices? You'll get an offset array indexed by the product of the axes of the input: julia> A = OffsetArray(1:3, 0:2) OffsetArray(::UnitRange{Int64}, 0:2) with eltype Int64 with indices 0:2: 1 2 3 julia> B = 4:6 4:6 julia> A*B' OffsetArray(::Array{Int64,2}, 0:2, 1:3) with eltype Int64 with indices 0:2×1:3: 4 5 6 8 10 12 12 15 18 > Whatever your answer, I suspect it is more cognitive overhead to remember than "always 1 based" or "always 0 based". Sure, but the real point here is that in most situations, you don't actually care what the axes are, because you use the higher level abstractions (e.g. iteration over elements or the index space, linear algebra operations, broadcasts, etc.), which all know how to deal with arbitrary axes. The only time you should ever really have to think about what your axes are is if there's some practical relevance to your problem (OffsetArrays are used heavily in the images stack).
- rrock 8y agoNot really. Imagine taking a rectangular region of interest from an image. With offset arrays, you can use the original indices if that suits you. I’d say that’s strictly better than using always zero based offsets.
- simonbyrne 8y agoWell for FFTs you really want periodic indices. Luckily Julia has those too: https://github.com/JuliaArrays/FFTViews.jl https://github.com/JuliaArrays/FFTViews.jl
- civility 8y agoI do a lot of FFTs for a living - I really want my zeroth frequency in my zeroth bin. Negative indices (as done by Python and other places) are nice though. This points to another example where 0-based should be preferred. When doing modulo arithmetic, 0..N-1 mod N gives 0..N-1, but 1..N mod N puts the zero at the end. I also cringe at languages where -1 mod N does not equal N-1.
- jacobolus 8y agoYes, people should never use “mod” or % as a synonym for “remainder”. It is horrible. For any language with a mod operator, a mod b should always be equal to (a + k×b) mod b for any integer k. Breaking this invariant makes the mod operator useless in pretty much every application I ever have for it. In e.g. JavaScript I need to define a silly helper function like mod = (x,y) => x%y + y*(x%y && x>0^y>0) And then remember to never use the native % operator.
- simonbyrne 8y agoWhat language defines % as mod and not remainder?
- jacobolus 8y agoAccording to Wikipedia: Perl, Python, Lua, Ruby, Tcl, R (as %%), Smalltalk (as \\), various other languages under some alternate name, sometimes with the two variants given different names. The other (“remainder”) version which takes its sign from the first argument is pretty much worthless in practice. IMO it doesn’t need any name at all. But what it definitely doesn’t need is a shorter and more convenient name than the useful modulo operator. Its ubiquity is a serious screwup in programming language design, albeit largely accidental.