I had a crazy dream, where I was back at University, but this time studying computer science. We were writing a function to calculate an arithmetic mean of an array of numbers. A task obviously too simple for college course, but with dreams you get what you are given.
Discussion started with this function:
-
function average(arr) {
-
var i, sum = 0;
-
for(i=0;i<arr.length;i++) {
-
sum += arr[i];
-
}
-
return sum/i;
-
}
- Download this code: /code/dreamjs.txt
Dream me, who by the way is significantly more bitchy than I ever am, wasn’t pleased and thought he could save few bytes by storing counter and sum inside of the array:
-
function average(arr) {
-
// Store counter in array[0] and sum in array[1]
-
if (arr.length < 3) {
-
return arr.length == 2 ? arr[0]+arr[1] : arr[0];
-
} else {
-
arr[1] = arr[0]+arr[1];
-
arr[0] = 2;
-
for(;arr[0]<arr.length;arr[0]++) {
-
arr[1] += arr[arr[0]];
-
}
-
}
-
return arr[1]/arr[0];
-
}
- Download this code: /code/dreamjs2.txt
This looked ugly, but what bothered him (me?) was more that it also had a bug. Integer in Javascript is limited to 2 53 , which is a lot, but sum can still overflow or underflow it. Since mean can never be smaller than smallest or bigger than biggest number in a list, I could fix it by writing:
-
function average(arr) {
-
var n = arr.length, sum=0;
-
while (arr.length) {
-
sum += arr.pop()/n;
-
}
-
return sum;
-
}
- Download this code: /code/dreamjs3.txt
End of dream. Everything edited for sanity and brevity.
I don’t have much to say about second program except that I would never write something so ugly just to save 16 bytes in a function like this. I wouldn’t even use Javascript if memory was that important.
I am more intrigued by third program. Bug in second is definitely there, even though few of us operate with numbers big enough to encounter it.
It’s interesting, because if I was awake, I would probably never think of it. I used to worry about bugs like this all the time, when I was coding in C. It was an unavoidable consequence of the language.
I guess what I am getting at is that it is nice to code in a high-level language and for the most part not think about implementation details like this, but only as long as you actually know them so your brain gets triggered when they matter. Speaking of details, I bet those divisions can cause rounding errors.
[...] this is not a travel post. A year ago I wrote my yearly review and it’s time to write a new one. Looking back at this year I feel disappointed. It [...]