Wrong rounding when getting an average

Hi,

I have a short sketch for a D1 mini which uses the ultrasound board HC-SR04 to measure a distance.
As the measurements are rather unstable (for example varying between 7 and 15 for a 14cm distance) I thought to always do 10 measurements and calculate the average.
What I don't get now is: from 10 measurements my total is 149. When I divide this by 10, I get 14. But with proper rounding this should come as 15.

Here my code:

int checkDistance() {
  
  long duration;
  int distance;
  int distance_inc;

  distance = 0;

  // make 10 measurements and add up all values
  for (int i = 0; i < 10; i++) {
    
      // send trigger to HC-SRD4
    digitalWrite(trigPin, LOW); 
    delayMicroseconds(2); 
    digitalWrite(trigPin, HIGH); 
    delayMicroseconds(10); 
    digitalWrite(trigPin, LOW);
    // measure the duration between the trigger and the return of the signal in micro-seconds
    duration = pulseIn(echoPin, HIGH); 
    // calculate the distance in cm
    // deduct 9cm to get reference level 0
    // distance = (duration * 0.034 / 2) - 9;
    // or without bias:
    distance_inc = (duration * 0.034 / 2);
    distance = distance + distance_inc;

    Serial.printf("increment: %i\n", distance_inc);
    Serial.printf("Distance: %i\n", distance);

    delay(100);
   
  }

  distance = round(distance / 10); // get average of 10 measurements
  
  return distance;
}

What am I not getting here?

Thanks
Matthias

But you're not rounding.
There are no fractions in an integer division.

So you mean I should add long numbers, divide and then convert to integer?

  Serial.println(149 / 10);
  Serial.println(149 / 10.0);

Compare the results of the 2 print statements
If you divide by an integer you get an integer result

No.
Just add half the number of samples (5 in this case) to the sum, and then divide by ten.

Sorry, this I don’t understand.

Rather than saying you don't understand, you could have tried it.

(An alternative is to preset distance to five, instead of zero, and then your round would have "worked")

From a mathematical point of view this doesn't make sense as you telling me to distort the measurement. Hence I wasn't sure what you mean.
But what you are essentially telling me is, yes the rounding doesn't work the way as expected but there is a tweak around it.

However, @UKHeliBob's comment was helpful. Thanks, now it works.

As opposed to distorting the result? :wink:

Edit: from a mathematical POV, the way you're doing it makes little sense.
Sum the durations, divide only once.

C/C++ doesn't round automatically, it truncates. For example, a value of 9.99 becomes 9, etc.

Rounding works exactly as expected, just not as you had hoped

If you divide an integer by an integer you get an integer result. 149.0 / 10 = 14.9
(For @matzr , I'm sure @UKHeliBob knows that already)

Sorry for not being more explicit.

I was commenting in the context of the posted sketch

The line: distance_inc = (duration * 0.034 / 2);
Is introducing random truncation errors each time.

Either use non-integers in the loop.
or add up the durations and incorporate the scaling into the final calculation.

eg distance = round ( total_duration * (0.017) / 10 )

note: I think the 0.017 turns the bracketed calculation to a real ?? so the original problem you had doesn't come into play.

Perhaps it does not make sense to you, but this is an accepted way of rounding during integer division.

This is what I ended up doing.
Thanks

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.