1

In my application I am reading an external value (int) from an EEG headset.

I thought that the value was read once a second but from my logcat report it seems that it is being read more than that.

This is disrupting my intentions as I want to calculate the average of the values. I am trying to do so using an increment operator called count.

Note that the values being read from the headset can only be from 1-100, so the output for average has to be incorrect as it is 168.

What am I doing wrong?

Current code:

Where value is being recorded:

case TGDevice.MSG_MEDITATION:

                //BELOW CODE RELATES TO SAVING AN AVERAGE VALUE

                meditationValues.add(msg.arg1); 
                count++;

                for(int i = 0; i < meditationValues.size(); i++){

                    totalofMedLevels += meditationValues.get(i);

                    Log.d("Total", "Total : " + totalofMedLevels);
                    Log.d("Count ", "Count: " + count);

                }

Calculating average:

public void getAverageValue(){
            //stop device so that the values can be recorded
            device.stop();


            averageMedLevel=totalofMedLevels/count; 

            Log.d("Average level:", "Average: " + averageMedLevel);

        }

Logcat Output:

For total:

07-14 14:16:44.312: D/Total(30422): Total : 301
07-14 14:16:45.313: D/Total(30422): Total : 301
07-14 14:16:45.313: D/Total(30422): Total : 301
07-14 14:16:45.313: D/Total(30422): Total : 301
07-14 14:16:45.323: D/Total(30422): Total : 301
07-14 14:16:45.323: D/Total(30422): Total : 301
07-14 14:16:45.323: D/Total(30422): Total : 301
07-14 14:16:45.323: D/Total(30422): Total : 342
07-14 14:16:45.323: D/Total(30422): Total : 406
07-14 14:16:45.323: D/Total(30422): Total : 456
07-14 14:16:45.323: D/Total(30422): Total : 496
07-14 14:16:46.314: D/Total(30422): Total : 496
07-14 14:16:46.314: D/Total(30422): Total : 496
07-14 14:16:46.314: D/Total(30422): Total : 496
07-14 14:16:46.314: D/Total(30422): Total : 496
07-14 14:16:46.314: D/Total(30422): Total : 496
07-14 14:16:46.314: D/Total(30422): Total : 496
07-14 14:16:46.324: D/Total(30422): Total : 537
07-14 14:16:46.324: D/Total(30422): Total : 601
07-14 14:16:46.324: D/Total(30422): Total : 651
07-14 14:16:46.324: D/Total(30422): Total : 691
07-14 14:16:46.324: D/Total(30422): Total : 725
07-14 14:16:47.285: D/Total(30422): Total : 725
07-14 14:16:47.285: D/Total(30422): Total : 725
07-14 14:16:47.285: D/Total(30422): Total : 725
07-14 14:16:47.285: D/Total(30422): Total : 725
07-14 14:16:47.285: D/Total(30422): Total : 725

For count:

07-14 14:16:47.285: D/Count(30422): Count: 12
07-14 14:16:47.285: D/Count(30422): Count: 12
07-14 14:16:47.285: D/Count(30422): Count: 12
07-14 14:16:47.285: D/Count(30422): Count: 12
07-14 14:16:47.285: D/Count(30422): Count: 12
07-14 14:16:47.295: D/Count(30422): Count: 12
07-14 14:16:47.295: D/Count(30422): Count: 12
07-14 14:16:47.295: D/Count(30422): Count: 12
07-14 14:16:47.295: D/Count(30422): Count: 12
07-14 14:16:47.295: D/Count(30422): Count: 12
07-14 14:16:47.295: D/Count(30422): Count: 12
07-14 14:16:48.286: D/Count(30422): Count: 13
07-14 14:16:48.286: D/Count(30422): Count: 13
07-14 14:16:48.286: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13
07-14 14:16:48.296: D/Count(30422): Count: 13

For average:

07-14 14:16:53.281: D/Average level:(30422): Average: 168

EDIT (TRYING TO ONLY SAVE A VALUE IF IT IS ABOVE 0):

if((msg.arg1)!=0){

                    meditationValues.add(msg.arg1); 

                }



                for(int i = 0; i < meditationValues.size(); i++){

                    //totalofMedLevels += meditationValues.get(i); 
                    totalofMedLevels+=msg.arg1;
                    count++; 

                    Log.d("Total", "Total : " + totalofMedLevels);
                    Log.d("Count ", "Count: " + count);

                }
5
  • I think you should increment count inside the for loop Commented Jul 14, 2014 at 13:32
  • If you want to force check every second then you could use System.currentTimeMillis() to save the previous iteration and check if you want to accept the incoming message to stick to that one second time frame; otherwise ignore it. Commented Jul 14, 2014 at 13:35
  • totalofMedLevels is being incremented by the whole loop every time you go through it and then accessed later. This is unlikely not the intention. It should probably be reset to 0 before each loop iteration. Or you should only add the latest entry. Commented Jul 14, 2014 at 13:36
  • Thanks a lot for your help, How actually would I do this? Would incrementing the for loop each second, as described above, solve the issue? Commented Jul 14, 2014 at 13:37
  • count = count + meditationValues.size() Commented Jul 14, 2014 at 13:37

5 Answers 5

4

It seems like every time you get a new value, you traverse the whole list of values and add them all again to "totalofMedLevels". Replacing the above code with

totalofMedLevels += msg.arg1;
count++;

should solve the problem. If not, you aren't providing enough information (that is, showing enough code).

Sign up to request clarification or add additional context in comments.

3 Comments

Either that, or you could reset totalofMedLevels to 0 before you loop through the values. In any case, I agree that this is the problem.
Thank you. Can you please see my edit to the question (at the bottom). There is a connection issue at the start of the app for a few seconds where the values are automatically 0. I only want the values and their associated counts to be added if they are above 0. Is my code correct for this?
You are still traversing the whole list ... You don't need the for-loop at all. Or you can do what @AriRoth said. if(msg.arg1 != 0) { meditationValues.add(msg.arg1); totalofMedLevels+=msg.arg1; count++; } would be correct, IMO.
1

I suppose the switch - case gets called from a Listener. So every time this is called you are iterating over the size of your List and adding the values to the class variable which is creating the problem. Change your code to this :

case TGDevice.MSG_MEDITATION:
         meditationValues.add(msg.arg1); 
         break;


public void getAverageValue(){
        device.stop();

        for(int i = 0; i <= meditationValues.size(); i++){
                totalofMedLevels += meditationValues.get(i);
                Log.d("Total", "Total : " + totalofMedLevels);
                Log.d("Count ", "Count: " + i + 1);
        }

        averageMedLevel = totalofMedLevels/meditationValues.size();
        Log.d("Average level:", "Average: " + averageMedLevel);
  }

Comments

0

why not just use the size of the array: averageMedLevel=totalofMedLevels/meditationValues.size()

1 Comment

I tried this, but it did not work for me. It gave me the same output as above. That is why I switched to the count method.
0

Clean up your code and the answer will become apparent.

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * @author DShaw
 *
 */
public class Meditation {

    private List<Integer> values;

    public Meditation()
    {
        values = new ArrayList<Integer>();
    }

    public double getSum() {
         double sum = 0; 
         for (Integer i:values)
             sum = sum + i;
         return sum;
    }

    public int getCount()
    {
        return values.size();
    }

    public void addValue(Integer value)
    {
        values.add(value);
    }

    public Double getAverage()
    {
        return getSum()/getCount();
    }

    public static void main(String[] args)
    {
        Meditation m = new Meditation();

        Random r = new Random(System.currentTimeMillis());

        for (int i=0; i < 1000; i++)
        {
            Integer randInt = r.nextInt(100);
            m.addValue(randInt);
            System.out.println("Average for " + 
                               m.getCount() + 
                               " items: " + 
                               m.getAverage());
        }
    }
}

Comments

0

You're getting a value bigger than expected/possible because your denominator (count) is not what it should be. Say you have 4 values in the array 0, 0, 100, 100 the average is obviously 50 (200/4) but if for some reason the denominator is wrong the average appears to be bigger. For example if you miscount the number of items as 3 then the average appears to be ~66 or worse only 2 are counted 200/2 = 100.

Since count is the issue I think this:
If you want to use a variable (count in your case) to track the size of the array then you need to increment it inside of the for loop.
Or alternatively, add set it equal to the size of the original array.

meditationValues.add(msg.arg1); 
count++;

for(int i = 0; i < meditationValues.size(); i++){
  totalofMedLevels += meditationValues.get(i);

  Log.d("Total", "Total : " + totalofMedLevels);
  Log.d("Count ", "Count: " + count);
  case++;
}

or add the size of the array to the count variable after the for loop.

for(...){
   .....
   .....
}
case += meditationValues.size();

regards,

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.