Comment by jperras
11 years ago
Similarly, the `average` package on NPM is one that I came across:
https://www.npmjs.com/package/average
var average = require('average');
var result = average([2, 5, 0, 1, 25, 7, 3, 0, 0, 10]);
console.log('The average for all the values is:', result);
It's hard to not stare at that in complete disbelief; someone thought that it was worthwhile to create a package for determining the mean of an array of numbers.
You know what's worse? Javascript numbers are all floating point numbers, which means integers are 53 bits long. So, you might think this library would try to address issues this can cause, but nope, this is the average statement you'd write if you didn't know was a mantissa was and had never heard of big.js, bignumber.js, decimal.js, crunch.js or even strint (which represents integers as strings because wtf not).
Not to mention the fact that adding many floating point numbers in a naive way results in a serious error accumulation, which is why things like Kahan summation algorithm[1] exist.
[1] - https://en.wikipedia.org/wiki/Kahan_summation_algorithm
Every once in a while, I come to HN, and inevitably find a post about some new JavaScript technology on the front page, wherein I find some comment that gives me a new appreciation for the web app language I use at work, which fortunately is not JavaScript.
I'd be interested to know what language it is.
1 reply →
What is the web app language you use at work? I assume you're talking about something that runs on the client -- a web browser -- so it probably compiles down to JavaScript, right? JS literally has no numeric type that isn't a float, so how does your language escape this fundamental limitation?
12 replies →
That's not true. In most javascript implementations, integers will be represented by real 32 bit integers.
How does that help? Besides they overflow to doubles if they get bigger than 2^31-1 anyway.
The problem with a naive average like this is that if you're averaging a bunch of big numbers there is a very high chance of overflow when you're summing, so even if all the numbers fit in 32 or 53 bits your calculation will be off.
If you're not averaging thousands of large numbers, why are you even using a package instead of nums.reduce((a,b)=>a+b) / nums.length anyway?
How does storing integers in 32-bit values help the issue of integers being truncated to 53 bits?
4 replies →
Source? I find this very hard to believe. 1. How does the engine know of it should be an integer or not? 2. Why would they have a special case for this, it won't benefit accuracy and treating them in a special way probably hurts performance more than just always keeping it as doubles.
As long as everything used is really an integer and that everyone you work with is careful to keep things as ints (oring with 0 and such)
Well a bunch of standard libraries have sum defined, right?
JavaScript has suffered from a lack of a standard library for a while. Having a small package like this means that (in theory) everyone is using the same bug free version of summing instead of writing their own.
Honestly having JS start building a standard library at this point would be wonderful.
For now I suggest using lodash functions exported as modules.
For example: https://www.npmjs.com/package/lodash.mean
Or, in light of `left-pad`: https://www.npmjs.com/package/lodash.padstart
You get the benefit of a "small, focused" module but still rely on a large and stable project with a great maintainer that cares about performance and testability.
There's already `Array.prototype.reduce()` in most browsers, which will do summing, string concatenation, and any other kind of aggregation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
If you need something more convenient I highly recommend just adding lodash and getting a whole bag of rock-solid awesome tools.
reduce isn't a safe way to add floating-point numbers unless your accumulator is much more precise than your array values. You'll end up with what they call "catastrophic cancellation".
And they won't let you have fixed-point in JavaScript!
2 replies →
here is the source for that npm package
https://github.com/bytespider/average/blob/master/src/averag...
and here is the code copied out in full
module.exports = function average(values) { for (var i = 0, sum = 0; i < values.length; ++i) { sum += values[i]; } return sum / values.length; };
is this worth adding a dependency to your build for?
Sounds like the author was aiming for something to put on his resume: e.g., "Author of 25 libraries on NPM, some with more than 500K downloads." etc...
Well if I was interviewing the guy, my second or third question would be "tell me about these packages you published on NPM"
It's going to be damn hard to make an average function sound impressive.
I think you're seriously overestimating quality of the average programmer candidate.
Someone who understands what NPM is, has written and published working code (even stupid code) is miles ahead of the curve already.
Most companies in the world, especially non-software companies, don't go for 5% hacker gurus. Attracting someone vaguely competent is already a blessing.
1 reply →
In JavaScript, the API could be fairly complex. Thing is, JavaScript doesn't have arrays of numbers. So, what should the function do if the array passed in contains a null, an undefined, a string such as "7", "012", "008", or "2+3", a function, another array, a hash, etc?
I can easily see this grow into a function accepting options indicating such things as "null values are zeroes", "ignore null values", "evaluate string arguments", etc, or maybe into a factory that produces customized averaging functions.
For example, average([null,1,2,3],[4,5]) could either be 3 (the average of all numbers), 2.5 (sum of numbers divided by number of 'root' items), undefined (input format error), 3.25 (average of average of [1,2,3] and average of [4,5]), etc.
And what if it gets passed arrays of equal size? "average([1,2,3],[7,4,5])" could easily be interpreted as a vector average, and produce [4,3,4]
Silly? Yes, but if you want to write a robust library in JavaScript, you have to think about what to do with all these kinds of input.
And of course, there are the simple variants of harmonic mean, arithmetic mean, and geometric mean, and several others (https://en.m.wikipedia.org/wiki/Average)
5 replies →
Im of the mind most employers are looking for "have you done stuff" "can you do stuff". Veey rarely are they looking for anyone extraordinary, simply a tool that works
1 reply →
That plus perhaps some kind of dopamine kick these people get out of this whole charade... Sindre Sorhus keeps describing himself as an "Open Source addict", after all.
This sounds like a symptom of an inadequate standard library. I do expect to be able to call "average" on a list of numbers without writing it myself, but I expect that to be part of the language not a 3rd party package.
> I do expect to be able to call "average" on a list of numbers without writing it myself
Just out of interest, what kinds of functions would you expect to have to write yourself, if you're not happy about calculating the average of a list of numbers?
Alright, take a simple function like average. How might someone naively calculate the average?
Which will fail but will probably be caught in the code review. Then a cleverer developer might think to write
Which will also fail but in more subtle ways, hopefully the senior dev will catch it in the code review.
Then they correct it to
But this could further optimized and might still be dangerous. This one might not be fixed at all in the code review.
The best algorithm might be Knuth's which is fairly non-trivial and might not even be the fastest/most efficient given certain unique JS optimizations.
Do you want to do this for every 'trivial' function or would you rather import average where (in theory) someone knowledgeable has already done this work and benchmarks for you and you get the best performing algorithm basically for free?
6 replies →
Those that are unique to the problem I'm actually trying to solve, and not already in the standard libraries or well-maintained packages of mainstream languages.
6 replies →
It should, but the ECMAScript spec doesn't have it, and Node.js team prefers to keep the core libraries to a minimum and definitely do not want to modify prototypes. Thus we depend on userland to provide those features for us.
Thats why somebody should fork Node and start building a batteries included standard library.
1 reply →
I think the scarier thing there is this line: "0.0.1 is the latest of 2 releases"
I wonder if there will be a 3rd release with an updated averaging function.
Edit: to be fair, it was an optimization from reduce to for loop [https://github.com/bytespider/average/commit/7d1e2baa8b8304d...]
I'm thinking that someone wanted to learn about building and publishing a package and the ecosystem so they made this computationally trivial thing as a practical exercise.
Pretty much every package management system gets cruft in it like this. Example: for a long time someone had uploaded a random Wordpress core install into Bower.
And 54 people found it a worthwhile package to install _this week alone_.
That could be one dependent module that got installed in 54 places. More likely, it was mostly various bots that install everything on some semi-regular schedule.
Let's say these are just prescient trolls. For our sanity.
While it demonstrates the problem of npm lacking namespaces (such that the word "average" is wasted on such a trivial implementation)...it doesn't seem anyone was using that library
npm has namespaces. https://docs.npmjs.com/misc/scope
That package is, at best, average...
ducks
(Edit: typo)
Don't be .... Mean.
Yes, but it's MIT licensed. We also need average_GPL to go with it.
You bring up a good point with respect to copyright/licensing --- at what point does code stop being copyrightable and become public domain simply due to pure triviality? There are not very many sane ways to write an averaging function, and the most straightforward one (add up all the value, then divide) would probably be present in tons of other codebases.