Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I know this might seem like an absolutely silly question to ask, yet I am too curious not to ask...
Why did "i" and "j" become THE variables to use as counters in most control structures?
Although common sense tells me they are just like X, which is used for representing unknown values, I can't help to think that there must be a reason why everyone gets taught the same way over and over again.
Is it because it is actually recommended for best practices, or a convention, or does it have some obscure reason behind it?
Just in case, I know I can give them whatever name I want and that variables names are not relevant.
It comes ultimately from mathematics: the summation notation traditionally uses i for the first index, j for the second, and so on. Example (from http://en.wikipedia.org/wiki/Summation):
It's also used that way for collections of things, like if you have a bunch of variables x1, x2, ... xn, then an arbitrary one will be known as xi.
As for why it's that way, I imagine SLaks is correct and it's because I is the first letter in Index.
I believe it dates back to Fortran. Variables starting with I through Q were integer by default, the others were real. This meant that I was the first integer variable, and J the second, etc., so they fell towards use in loops.
Mathematicians were using i,j,k to designate integers in algebra (subscripts, series, summations etc) long before (e.g 1836 or 1816) computers were around (this is the origin of the FORTRAN variable type defaults). The habit of using letters from the end of the alphabet (...,x,y,z) for unknown variables and from the beginning (a,b,c...) for constants is generally attributed to Rene Descartes, (see also here) so I assume i,j,k...n (in the middle of the alphabet) for integers is likely due to him too.
i = integer
Comes from Fortran where integer variables had to start with the letters I through N and real variables started with the other letters. Thus I was the first and shortest integer variable name. Fortran was one of the earliest programming languages in widespread use and the habits developed by programmers using it carried over to other languages.
EDIT: I have no problem with the answer that it derives from mathematics. Undoubtedly that is where the Fortran designers got their inspiration. The fact is, for me anyway, when I started to program in Fortran we used I, J, K, ... for loop counters because they were short and the first legally allowed variable names for integers. As a sophomore in H.S. I had probably heard of Descartes (and a very few others), but made very little connection to mathematics when programming. In fact, the first course I took was called "Fortran for Business" and was taught not by the math faculty, but the business/econ faculty.
For me, at least, the naming of variables had little to do with mathematics, but everything due to the habits I picked up writing Fortran code that I carried into other languages.
i stands for Index.
j comes after i.
These symbols were used as matrix indexes in mathematics long before electronic computers were invented.
I think it's most likely derived from index (in the mathematical sense) - it's used commonly as an index in sums or other set-based operations, and most likely has been used that way since before there were programming languages.
There's a preference in maths for using consecutive letters in the alphabet for "anonymous" variables used in a similar way. Hence, not just "i, j, k", but also "f, g, h", "p, q, r", "x, y, z" (rarely with "u, v, w" prepended), and "α, β, γ".
Now "f, g, h" and "x, y, z" are not used freely: the former is for functions, the latter for dimensions. "p, q, r" are also often used for functions.
Then there are other constraints on available sequences: "l" and "o" are avoided, because they look too much like "1" and "0" in many fonts. "t" is often used for time, "d & δ" for differentials, and "a, s, m, v" for the physical measures of acceleration, displacement, mass, and velocity. That leaves not so many gaps of three consecutive letters without unwanted associations in mathematics for indices.
Then, as several others have noticed, conventions from mathematics had a strong influence on early programming conventions, and "α, β, γ" weren't available in many early character sets.
I found another possible answer that could be that i, j, and k come from Hamilton's Quaternions.
Euler picked i for the imaginary unit.
Hamilton needed two more square roots of -1:
ii = jj = kk = ijk = -1
Hamilton was really influential, and quaternions were the standard way to do 3D analysis before 1900. By then, mathematicians were used to thinking of (ijk) as a matched set.
Vector calculus replaced quaternionic analysis in the 1890s because it was a better way to write Maxwell's equations. But people tended to write vector quantities as like this: (3i-2j+k) instead of (3,-2,1). So (ijk) became the standard basis vectors in R^3.
Finally, physicists started using group theory to describe symmetries in systems of differential equations. So (ijk) started to connote "vectors that get swapped around by permutation groups," then drifted towards "index-like things that take on all possible values in some specified set," which is basically what they mean in a for loop.
by discarding (a little biased)
a seems an array
b seems another array
c seems a language name
d seems another language name
e seems exception
f looks bad in combination with "for" (for f, a pickup?)
g seems g force
h seems height
i seems an index
j seems i (another index)
k seems a constant k
l seems a number one (1)
m seems a matrix
n seems a node
o seems an output
p sounds like a pointer
q seems a queue
r seems a return value
s seems a string
t looks like time
u reserved for UVW mapping or electic phase
v reserved for UVW mapping or electic phase or a vector
w reserved for UVW mapping or electic phase or a weight
x seems an axis (or an unknown variable)
y seems an axis
z seems a third axis
One sunny afternoon, Archimedes what pondering (as was usual for sunny afternoons) and ran into his buddy Eratosthenes.
Archimedes said, "Archimedes to Eratosthenes greeting! I'm trying to come up with a solution to the ratio of several spherical rigid bodies in equilibrium. I wish to iterate over these bodies multiple times, but I'm having a frightful time keeping track of how many iterations I've done!"
Eratosthenes said, "Why Archimedes, you ripe plum of a kidder, you could merely mark successive rows of lines in the sand, each keeping track of the number of iterations you've done within iteration!"
Archimedes cried out to the world that his great friend was undeniably a shining beacon of intelligence for coming up with such a simple solution. But Archimedes remarked that he likes to walk in circles around his sand pit while he ponders. Thus, there was risk of losing track of which row was on top, and which was on bottom.
"Perhaps I should mark these rows with a letter of the alphabet just off to the side so that I will always know which row is which! What think you of that?" he asked, then added, "But Eratosthenes... whatever letters shall I use?"
Eratosthenes was sure he didn't know which letters would be best, and said as much to Archimedes. But Archimedes was unsatisfied and continued to prod the poor librarian to choose, at least, the two letters that he would require for his current sphere equilibrium solution.
Eratosthenes, finally tired of the incessant request for two letters, yelled, "I JUST DON'T KNOW!!!"
So Archimedes chose the first two letters in Eratosthenes' exclamatory sentence, and thanked his friend for the contribution.
These symbols were quickly adopted by ancient Greek Java developers, and the rest is, well... history.
i think it's because a lot of loops use an Int type variable to do the counting, like
for (int i = 0; etc
and when you type, you actually speak it out in your head (like when you read), so in your mind, you say 'int....'
and when you have to make up a letter right after that 'int....' , you say / type the 'i' because that is the first letter you think of when you've just said 'int'
like you spell a word to kids who start learning reading you spell words for them by using names, like this:
WORD spells William W, Ok O, Ruby R, Done D
So you say Int I, Double d, Float f, string s etc. based on the first letter.
And j is used because when you have done int I, J follows right after it.
I think it's a combination of the other mentioned reasons :
For starters, 'i' was commonly used by mathematicians in their notation, and in the early days of computing with languages that weren't binary (ie had to be parsed and lexed in some fashion), the vast majority of users of computers were also mathematicians (... and scientists and engineers) so the notation fell into use in computer languages for programming loops, and has kind of just stuck around ever since.
Combine this with the fact that screen space in those very early days was very limited, as was memory, it made sense to keep shorter variable names.
Possibly historical ?
FORTRAN, aurguably the first high level language, defined i,j,k,l,m as Integer datatypes by default, and loops could only be controlled by integer variable, the convention continues ?
eg:
do 100 i= j,100,5
....
100 continue
....
i = iterator, i = index, i = integer
Which ever you figure "i" stands for it still "fits the bill".
Also, unless you have only a single line of code within that loop, you should probably be naming the iterator/index/integer variable to something more meaningful. Like: employeeIndex
BTW, I usually use "i" in my simple iterator loops; unless of course it contains multiple lines of code.
i = iota, j = jot; both small changes.
iota is the smallest letter in the greek alphabet; in the English language it's meaning is linked to small changes, as in "not one iota" (from a phrase in the New Testament: "until heaven and earth pass away, not an iota, not a dot, will pass from the Law" (Mt 5:18)).
A counter represents a small change in a value.
And from iota comes jot (iot), which is also a synonym for a small change.
cf. http://en.wikipedia.org/wiki/Iota
Well from Mathematics: (for latin letters)
a,b: used as constants or as integers for a rational number
c: a constant
d: derivative
e: Euler's number
f,g,h: functions
i,j,k: are indexes (also unit vectors and the quaternions)
l: generally not used. looks like 1
m,n: are rows and columns of matrices or as integers for rational numbers
o: also not used (unless you're in little o notation)
p,q: often used as primes
r: sometimes a spatial change of variable other times related to prime numbers
s,t: spatial and temporal variables or s is used as a change of variable for t
u,v,w: change of variable
x,y,z: variables
Many possible main reasons, I guess:
mathematicians use i and j for Natural Numbers in formulas (the ones that use Complex Numbers rarely, at least), so this carried over to programming
from C, i hints to int. And if you need another int then i2 is just way too long, so you decide to use j.
there are languages where the first letter decides the type, and i is then an integer.
It comes from Fortran, where i,j,k,l,m,n are implicitly integers.
It definitely comes from mathematics, which long preceded computer programming.
So, where did if come from in math? My completely uneducated guess is that it's as one fellow said, mathematicians like to use alphabetic clusters for similar things -- f, g, h for functions; x, y, z for numeric variables; p, q, r for logical variables; u, v, w for other sets of variables, especially in calculus; a, b, c for a lot of things. i, j, k comes in handy for iterative variables, and that about exhausts the possibilities. Why not m, n? Well, they are used for integers, but more often the end points of iterations rather than the iterative variables themselves.
Someone should ask a historian of mathematics.
Counters are so common in programs, and in the early days of computing, everything was at a premium...
Programmers naturally tried to conserve pixels, and the 'i' required fewer pixels than any other letter to represent. (Mathematicians, being lazy, picked it for the same reason - as the smallest glyph).
As stated previously, 'j' just naturally followed...
:)
I use it for a number of reasons.
Usually my loops are int based, so
you make a complete triangle on the
keyboard typing "int i" with the
exception of the space I handle with
my thumb. This is a very fast
sequence to type.
The "i" could stand for iterator, integer, increment, or index, each of which makes
logical sense.
With my personal uses set aside, the theory of it being derived from FORTRAN is correct, where integer vars used letters I - N.
I learned FORTRAN on a Control Data Corp. 3100 in 1965. Variables starting with 'I' through 'N' were implied to be integers. Ex: 'IGGY' and 'NORB' were integers, 'XMAX' and 'ALPHA' were floating-point. However, you could override this through explicit declaration.
I had a geek fight with someone over what the strategy pattern really is and I need a expert to settle the matter.
We both agree that the strategy pattern allows for the guts of a class (e.g., the behavior) to be swapped out at runtime while maintaining the same interface. However, her contention is that "For [the algorithms] to be a strategy, You would have to get the same results". My contention is that swapping an "algorithm" or logic of a class could mean that the results of the overridden operation are different, but that it still meets the purpose, intent (and classification) of the strategy pattern.
Her code example with comments:
By your definition, any subclasses of a class would be a strategy. They have the same method definitions (signatures), and are therefore interchangeable.
Interface Strategy
{
DoArithmatic(int[] a)
}
Class A : Strategy
public int DoArithmatic(int[]a)
{
int temp = 0;
for(int i =0; i< a.length; i++)
temp += a[i]
}
Class B : Strategy
public int DoArithmaticB(int[]a)
{
int temp = 0;
for(int i =a.length -1; i>-1; i--)
temp += a[i]
}
Class C : Strategy
public int DoArithmatic(int[]a)
{
int temp = 0;
for(int i =0; i< a.length; i++)
temp -= a;
}
int[] a = { 1,2,3 }
ClassA.DoArithmatic(a) = 6
ClassB.DoArithmatic(a) = 6
ClassC.DoArithmatic(a) = -6//This one is not interchangeable
The first two are strategies. Because for any input they will give you the EXACT same answer. the last one is not. Just because it gives you an int does not make it a strategy. They have to "DO" the same thing.
You can't use a "higher" abstraction term just to make them a strategy.
These all do "MATH" but they are not all doing the "same" thing in a different way. That is the essence of a strategy.
So, who's right?
You sir are correct and your coworker needs to read the GoF.
"The strategy pattern lets the algorithms vary independently from clients that use them."
See:
http://www.dofactory.com/Patterns/PatternStrategy.aspx
Technically, strategies can do whatever they want.
It is only when the "outer context" dictates some fixed and repeatable behaviour that cannot be captured in the programmatical interface (call them "desirable properties"), that you need to take care that your strategies are truly substitutable à la Liskov with respect to these desirable properties.
I support your opinion. Different strategies can do very different things as long as they can be used in the same context.
For example, if you want to visit each node in a tree, valid strategies could be:
Depths-first search pre-order
DFS post-order
BFS
randomized
...
All strategies would visit the nodes in a different order, yet the objective (visiting each node) would be the same. So if the order does not matter, either strategy fits your needs.
FWIW, the Wikipedia article agrees with you and has never heard of her position.
The first two are strategies. Becuase for any input they will give you the EXACT same answer. the last one is not. Just becuase it gives you an int does not make it a strategy. They have to "DO" the same thing.
They have to do the same thing, but that doesn't mean they give the exact same result. The motivating example from the GoF is one of different layout algorithms, or different register allocation algorithms. The strategies have the same goal - layout blocks of text and images on a page, or assigning virtual registers to hardware registers - but they don't have to create exactly the same result.
So if the goal of the Strategy in your example is to do any arithmetic with the input, then each example is a strategy for that goal. If the goal was to sum the array it is passed, DoArithmatic would have been called CalculateSum, and the final example would fail to conform to the contract of the strategy, and so violate LSP.
According to "Head first Design Patterns" (see here) page 24
"The Strategy Pattern defines a family of algorithms,
encapsulates each one, and makes them interchangeable.
Strategy lets the algorithm vary independently from
clients that use it. "
so sir you are correct, at least according to the people who defined the pattern, but what do they know.
You are. The point of the strategy is to substitute the algorithm. Whether they deliver the same result is a by-product of the desired behavior.
I think it would be more correct to say that the question of whether the strategies must be deterministically identical is outside the scope of the definition of the strategy pattern.
If a function always returns the same result for given inputs, it is deterministic. If two functions are deterministic and they always return the same value for the same inputs then they are deterministically equivalent. They may or may not have the same side effects; if they do then they are just plain equivalent.
Typically this is not the case. Let us consider an example that appears to require deterministic equivalence: sorting. You might think that if two comparer implementations fail to return the same result for the same inputs then at least one of them must be faulty, but this is not necessarily the case.
Sort orders vary between countries. Some places sort accent-insensitively. Some put McDuck with MacDuck, and so forth. These are strategies, this is a perfect application of strategy pattern, and the strategies are most certainly not deterministically equivalent.
You win.
I also have to agree. A good example would be a pricing calculator strategy. You could have different strategies for calculating the final amount of an invoice depending on several variables like quantity of items, type of customer, shipping destination, etc. Each of those strategies would definitely be expected to return a different result and it would still be considered a Strategy pattern.