0

I am having some calc inconsistency when trying to figure out some averages. Apparently I am doing something wrong, but I cannot figure it out.

I have an array of speed samples example:

[3.3, 3.3, 3.32, 3.32, 3.22, 3.22, 3.14, 3.14, 3, 3, 3, 3, 3.02, 3.02, 2.96, 2.96, 2.92, 2.92, 2.88, 2.88, 2.88, 2.88, 2.86, 2.86, 2.86, 2.86, 2.86, 2.86, 2.88, 2.88, 2.88, 2.88, 2.86, 2.86, 2.84, 2.84, 2.86, 2.86, 2.88, 2.88, 2.9, 2.9, 2.86, 2.86, 2.84, 2.84, 2.84, 2.84, 2.82, 2.82, 2.8, 2.8, 2.64, 2.64, 0, 0, 2.22, 2.22, 2.3, 2.3, 2.4, 2.4, 2.44, 2.44, 2.58, 2.58, 2.6, 2.6, 2.62, 2.62, 2.62, 2.62, 2.58, 2.58, 2.54, 2.54, 2.52, 2.52, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.48, 2.48, 2.46, 2.46, 2.44, 2.44, 2.44, 2.44, 2.42, 2.42, 2.42, 2.42, 2.42, 2.42, 2.42, 2.42]

Now in order to find the average speed I do

[3.3, 3.3, 3.32, 3.32, 3.22, 3.22, 3.14, 3.14, 3, 3, 3, 3, 3.02, 3.02, 2.96, 2.96, 2.92, 2.92, 2.88, 2.88, 2.88, 2.88, 2.86, 2.86, 2.86, 2.86, 2.86, 2.86, 2.88, 2.88, 2.88, 2.88, 2.86, 2.86, 2.84, 2.84, 2.86, 2.86, 2.88, 2.88, 2.9, 2.9, 2.86, 2.86, 2.84, 2.84, 2.84, 2.84, 2.82, 2.82, 2.8, 2.8, 2.64, 2.64, 0, 0, 2.22, 2.22, 2.3, 2.3, 2.4, 2.4, 2.44, 2.44, 2.58, 2.58, 2.6, 2.6, 2.62, 2.62, 2.62, 2.62, 2.58, 2.58, 2.54, 2.54, 2.52, 2.52, 2.5, 2.5, 2.5, 2.5, 2.5, 2.5, 2.48, 2.48, 2.46, 2.46, 2.44, 2.44, 2.44, 2.44, 2.42, 2.42, 2.42, 2.42, 2.42, 2.42, 2.42, 2.42]
.reduce(function(acc, val) { return acc + val; }, 0)/100

The result is: (m/s)

2.670800000000001

Now to convert to pace I do

1000/2.670800000000001 = 374.41964954320787

So 374.41964954320787 seconds

Now if I first convert that array of speed values to pace with the same conversion like

speedArray.map(v => 1000/v)

I get this array

[303.03030303030306, 303.03030303030306, 301.20481927710847, 301.20481927710847, 310.55900621118013, 310.55900621118013, 318.4713375796178, 318.4713375796178, 333.3333333333333, 333.3333333333333, 333.3333333333333, 333.3333333333333, 331.12582781456956, 331.12582781456956, 337.83783783783787, 337.83783783783787, 342.4657534246575, 342.4657534246575, 347.22222222222223, 347.22222222222223, 347.22222222222223, 347.22222222222223, 349.65034965034965, 349.65034965034965, 349.65034965034965, 349.65034965034965, 349.65034965034965, 349.65034965034965, 347.22222222222223, 347.22222222222223, 347.22222222222223, 347.22222222222223, 349.65034965034965, 349.65034965034965, 352.11267605633805, 352.11267605633805, 349.65034965034965, 349.65034965034965, 347.22222222222223, 347.22222222222223, 344.82758620689657, 344.82758620689657, 349.65034965034965, 349.65034965034965, 352.11267605633805, 352.11267605633805, 352.11267605633805, 352.11267605633805, 354.6099290780142, 354.6099290780142, 357.14285714285717, 357.14285714285717, 378.78787878787875, 378.78787878787875, Infinity, Infinity, 450.45045045045043, 450.45045045045043, 434.7826086956522, 434.7826086956522, 416.6666666666667, 416.6666666666667, 409.8360655737705, 409.8360655737705, 387.5968992248062, 387.5968992248062, 384.6153846153846, 384.6153846153846, 381.6793893129771, 381.6793893129771, 381.6793893129771, 381.6793893129771, 387.5968992248062, 387.5968992248062, 393.7007874015748, 393.7007874015748, 396.8253968253968, 396.8253968253968, 400, 400, 400, 400, 400, 400, 403.2258064516129, 403.2258064516129, 406.5040650406504, 406.5040650406504, 409.8360655737705, 409.8360655737705, 409.8360655737705, 409.8360655737705, 413.22314049586777, 413.22314049586777, 413.22314049586777, 413.22314049586777, 413.22314049586777, 413.22314049586777, 413.22314049586777, 413.22314049586777]

Now running the save AVG calculation on that

Like this oo.filter(v => v !== Infinity).reduce(function(acc, val) { return acc + val; }, 0)/98 370.3021539217866

The AVG pace of those samples is:

370.3021539217866

NOTICE above the array has 2 infinity values and that is why the division with 98 not 100

Which is not the same as converting the AVG SPEED to Pace

What can I be doing wrong?

Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117
  • 2
    you are dealing with floating point math. its imprecise by nature. – Daniel A. White Mar 04 '20 at 15:43
  • 4
    In the second version, you explicitly skip 2 values but the average computation still divides by 100. – Pointy Mar 04 '20 at 15:44
  • 1
    For the first array, you must filter out 0 values, because 1/0 => infinity – Ja͢ck Mar 04 '20 at 15:46
  • Good catch @Pointy but it doenst help it's worse let me update – Jimmy Kane Mar 04 '20 at 15:46
  • 1
    Does this answer your question? [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Heretic Monkey Mar 04 '20 at 15:48
  • Maybe multiply all values by a power of 10 and round them so they're all integers, then perform the operations, round again, and divide the result by the same factor? – Locoluis Mar 04 '20 at 15:50
  • I updated the question with diving with 98. Sorry for the wrong copy paste. Actually you can run the code (conversion) as seen. – Jimmy Kane Mar 04 '20 at 15:52
  • @HereticMonkey it might – Jimmy Kane Mar 04 '20 at 15:54
  • 1
    I don't think it's a problem with accuracy. I think it's an invalid algebraic transformation. The sum of the original speed values includes the two zeros; the other sum does not, so they don't participate in the calculation. That can't be right. – Pointy Mar 04 '20 at 16:01
  • @Pointy I think you are into something. Can you help me ? – Jimmy Kane Mar 04 '20 at 16:04
  • 1
    Well I'm not much of a mathematician; it just seems really suspicious. The original (first) version seems OK however. – Pointy Mar 04 '20 at 16:05
  • The problem thought is that I need to deal also with the pace thing. :-/ – Jimmy Kane Mar 04 '20 at 16:09
  • I agree with @Pointy. Removing the `0` values from the array should produce consistent results. –  Mar 04 '20 at 16:13
  • 1
    Well it's interesting, conceptually; if there are two zero speeds, that means those two "competitors" will *never* traverse a kilometer. Thus, either way, the average pace is a questionable concept. If you try this with a much smaller array with no zeros, then you get answers that are probably within normal floating point error range of each other. – Pointy Mar 04 '20 at 16:15
  • 2
    I think doing this calculation by hand, on paper, using two values `[10, 0]`, should illustrate where the issue lies. The average is `5 m/s`. The average pace is `200 s`. Converting each individual speed to a pace gives you `[100, Infinity]`. How does one take the average of 100 and infinity? Filtering out the infinity gives you `100`, which is very wrong. IMO, you just need to filter out bad data up-front, rather than at the end. –  Mar 04 '20 at 16:22
  • Guys even for comments you have been very helpful. Went for a run and I think I solved it. I was running and at the same time peeking at SO – Jimmy Kane Mar 04 '20 at 16:53
  • 1
    I started writing an answer a few times but SO doesn't support MathJax, so I gave it up. Doing some algebra with two numbers, A and B, shows why what you're trying to do isn't algabraicly sound. I think it might be worth asking about on [math.se]. –  Mar 04 '20 at 18:16
  • @Amy yup I think the question doesn't belong on SO. the comment from you above proves it. Here is about coding. Ill delete if you are fine with that . or Should I keep it for the comments? And hey thanks a lot for your time. – Jimmy Kane Mar 04 '20 at 18:21
  • 1
    @JimmyKane It's entirely up to you. I would delete this question eventually, but nothing says you need to delete it now. –  Mar 04 '20 at 18:24

0 Answers0