rwaldron / proposal-math-extensions

ES Math Extensions
61 stars 7 forks source link

`Math.sum`? #4

Open ljharb opened 8 years ago

ljharb commented 8 years ago

Simplifying things like Math.sum(...Object.values(x)) or Math.sum(...numbers) where previously we'd need .reduce((a, b) => a+ b)?

rwaldron commented 8 years ago

Since we're "pivoting" this proposal to be a broader Math update, I think this addition is solid.

ghost commented 8 years ago

If Math.sum makes it, Math.product might be useful, too.

kevinbarabash commented 7 years ago

Here's an attempt at being more specific:

Here's a possible implementation:

Math.sum = (...args) => {
   let result = 0;
   for (let i = 0; i < args.length; i++) {
      if (typeof args[i] !== 'number') {
          return NaN;
      }
      result += args[i];
      if (isNaN(result)) {
          return result;
      }
   }
   return result;
};
ljharb commented 7 years ago

Actually I think all arguments should be coerced ToNumber, like almost all builtin Math methods. In other words, it should definitely work on strings.

ljharb commented 7 years ago

Effectively, Math.sum = function sum(...args) { return args.reduce((a, b) => Number(a) + Number(b), 0); }' - I would be quite surprised if that polyfill did not match the spec.

kevinbarabash commented 7 years ago

TIL that Math methods coerce strings to numbers.

petamoriken commented 7 years ago

Why don't you adopt Kahan summation algorithm? https://en.wikipedia.org/wiki/Kahan_summation_algorithm

ljharb commented 7 years ago

That sounds like a specific implementation, which the spec usually does not dictate. That's the sort of thing that if it is not observable, an implementation is free to use.

petamoriken commented 7 years ago

@ljharb Kahan summation algorithm is a compensated summation (observable).

// Naive summation
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7].reduce(function(a, b) { return a + b })
// -> 15.299999999999999

// Kahan summation
require('kahan').sum([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7])
// -> 15.3

https://github.com/viktors/node-kahan

Stream API (Collection) in Java use this algorithm. http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/util/stream/Collectors.java#l538

micnic commented 6 years ago

@petamoriken Python has Math.fsum() for accurate floating point sum.

Maybe add both? :smile: Math.sum() - fast implementation and Math.fsum() - slower implementation, but more accurate

MaxGraey commented 5 years ago

I vote for single accurate Math.sum() which probably could use iterative pairwise summation like in Julia or Shewchuk's algorithm like in Python, but not Kahan summation which not always guarantee accurate results.

petamoriken commented 11 months ago

That's going to be a different proposal https://github.com/bakkot/proposal-math-sum

Rudxain commented 11 months ago

I agree with @ljharb, the algorithm should be implementation-defined. The only requirement the spec should impose, is to make the sum as accurate/precise as possible (by minimizing rounding-errors). This can be accomplished with summation-algorithms designed for F.P.-arithmetic, or by internally using BigFloats

ljharb commented 11 months ago

To be clear; the spec will need to include some algorithm. It’s just that it should be possible for implementations to choose another one that’s observably the same.