Live data from Hacker News

Calculating the mean of a list of numbers (2016)

hypothesis.works

31–40 of 96 posts

Re: Calculating the mean of a list of numbers (2016)

#31

This is the TXR Lisp interactive listener of TXR 214. Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet. 1> (defun mean (seq) (/ (sum seq) (len seq))) mean 2> (mean '(8.988465674311579e+307 8.98846567431158e+307)) ** out-of-range floating-point result ** during evaluation at expr-1:1 of form (sum seq) Works for me; error is caught. Breaking news: floating-point has a limited range! Detailed story at 11…

Similar correct result from sbcl.

Re: Calculating the mean of a list of numbers (2016)

#32

An 'online' mean calculation might resolve some of the common issues. Something like - def mean(ls): mu = 0.0 for i, x in enumerate(ls): mu = i/(i+1) * mu + x/(i+1) return mu

Even better if you can afford to sort the data and use a high precision type for mu. The algorithm will not be online any more and for python real numbers are usually double in practice. But in a constraint system where one has to work with float32, just using float64 for mu helps.

Re: Calculating the mean of a list of numbers (2016)

#34
I ran into a similar issue doing high accuracy dot-products. The solution was Kahan summation [1], which first adds the incremental value, then checks the result to see how much floating point error was introduced, then rolls that error into the next addition.

I suspect something similar could be done here, even if it would be a few times slower, to get an ulp-accurate mean regardless of the order/size of the individual elements.

1: https://en.wikipedia.org/wiki/Kahan_summation_algorithm

Re: Calculating the mean of a list of numbers (2016)

#35
post #6

If you're reaching these values then it's extremely likely that either: (a) You're doing something wrong (usually, not standardizing your data, etc.) which means that you're not thinking about the fact that computers have finite numerical precision and adjusting your problem accordingly (e.g., have a wide dynamic range of numbers). Or, (b) your problem is pretty ill-conditioned and there's probably no solving it in a…

Most of the issues discussed in the article are not from limits in precision, they're from overflows that arise from limits in the exponential range. Finding the average of 8e+307 and 8e+307 is a "low precision" problem, and even naive methods to avoid overflow will not hit limits on precision in this case (e.g. 8e+307/2 + 8e+307/2).

You're right that there are issues with precision and floating point math (the article touches on this a little), but the implementation is definitely wrong if it promises to work like in the case of Python's statistics library (which was correctly using the fractions library to store arbitrary numbers, but converted to a fraction in the wrong order).

Re: Calculating the mean of a list of numbers (2016)

#36
post #29
post #22

What about a "reduce" technique? Average the numbers in equal-sized chunks, then average those averages. You could even chunk the chunk averages and repeat the process as many levels down as you want to, and chunks could be as small as 2 each. I guess this still assumes that the largest number in the original list is less than or equal to the maximum floating point value, but otherwise you stay roughly in the same sp…

Unfortunately, by averaging the averages you skew the results. Average of averages does not produce the same result as averaging the whole list.

Average of equal size chunks' averages does. (mathematically)

Re: Calculating the mean of a list of numbers (2016)

#37
post #29
post #22

What about a "reduce" technique? Average the numbers in equal-sized chunks, then average those averages. You could even chunk the chunk averages and repeat the process as many levels down as you want to, and chunks could be as small as 2 each. I guess this still assumes that the largest number in the original list is less than or equal to the maximum floating point value, but otherwise you stay roughly in the same sp…

Unfortunately, by averaging the averages you skew the results. Average of averages does not produce the same result as averaging the whole list.

\left( \sum_{i=1}^m x_i/m + \sum_{i=m+1}^{2m} x_i/m \right) / 2 = \sum_{i=1}^{2m} x_i /(2m)

Re: Calculating the mean of a list of numbers (2016)

#38

This is the TXR Lisp interactive listener of TXR 214. Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet. 1> (defun mean (seq) (/ (sum seq) (len seq))) mean 2> (mean '(8.988465674311579e+307 8.98846567431158e+307)) ** out-of-range floating-point result ** during evaluation at expr-1:1 of form (sum seq) Works for me; error is caught. Breaking news: floating-point has a limited range! Detailed story at 11…

Or one could cheat, :) by using Scheme exact numbers:

  #lang racket/base
  (define (mean seq) (/ (apply + seq) (length seq)))
  (mean '(#e8.988465674311579e+307 #e8.98846567431158e+307))
89884656743115795000[...]

Re: Calculating the mean of a list of numbers (2016)

#39
post #22

What about a "reduce" technique? Average the numbers in equal-sized chunks, then average those averages. You could even chunk the chunk averages and repeat the process as many levels down as you want to, and chunks could be as small as 2 each. I guess this still assumes that the largest number in the original list is less than or equal to the maximum floating point value, but otherwise you stay roughly in the same sp…

I think this works perfectly if your list has 2^n elements. Otherwise, you have to resort to multiplying by imprecise fractions.

Re: Calculating the mean of a list of numbers (2016)

#40
post #2

An interesting article describing a useful framework. In addition to the largest numbers that floating point can handle, a related issue can come up with numbers that are not near the edge. A good student of floating point numbers will notice that there is a good chance you will get a different result summing a list of floating point numbers if they are sorted in a different order. This is due to the rounding error t…

> Thus, you should sort an array of floating point numbers and begin the summation with the smallest

Is this method more accurate than Kahan summation? And if so, is it worth the extra cost of sorting?

Post reply on HN