0
public class StampaInversa {

private static class NumberWithCounterAndAverage{
    private int number=0;
    private int counter=1;
    private int average=0;
    public int getNumber(){
        return number;
    }
    public int getCounter(){
        return counter;
    }
    public void setNumber(int number){
            this.number=number;
    }
    public void setCounter(int counter){
        this.counter+=counter;
    }

    public int getAverage(){
        return avrage;
    }
    public void setAverage(int average){
        this.average=average;
    }

    public String toString(){
        return "Number: "+number+"Counter "+counter+"Average "+average;
    }//toString
}//NumeroConContatore

public static void reversePrint(){
    Scanner sc= new Scanner(System.in);
    System.out.println("Insert number");
    int x=sc.nextInt();
    if(x==0) return;
    reverseprint();
    System.out.println(x);
}

public static int sumPrint(){
    Scanner sc=new Scanner(System.in);
    System.out.println("Insert number");
    int x=sc.nextInt();
    if(x!=0) x+=sumPrint();
    return x;
}

public static NumberWithCounterAndAverage printAverage(){
    Scanner sc=new Scanner(System.in);
    NumberWithCounterAndAverage ncc= new NumberWithCounterAndAverage();
    System.out.println("Insert number");
    int x=sc.nextInt();
    if(x!=0){
        NumberWithCounterAndAverage nccem= printAverage();
        ncc.setNumber(x+nccem.getNumber());
        ncc.setCounter(+nccem.getCounter());
    }
    if (x!=0){
        ncc.setAverage(ncc.getNumber()/(ncc.getCounter()-1));
    }
    return ncc;
}

public static void main(String[] args) {
    NumberWithCounterAndAverage nccem= printAverage();
    System.out.println(nccem.getCounter()+" "+nccem.getNumber()+" average "+nccem.getAverage());
}
}//StampaInversa

My prof. gave me an assignment: write tail recursive functions to calculate:
the sum of the number inserted from input till 0 is inserted;
the average of the number inserted till 0 is inserted;
the standard deviation of the number inserted till 0 is inserted;

The conditions to accomplish the assignment are:
No data structure allowed (arrays, arraryslist, LinkedList...), only ad hoc objects are allowed (such as the one that I have created: NumberWithCounterAndAverage)
No istance variables allowed, the variables must be own only by the functions.
The function must be recursive.

The functions in the code above work perfectly, but now I need to made a recursive function to calculate the standard deviation with the condition descripted above. Do you have any clue?

If it is still not clear how the function should be, tell me.

Triad sou.
  • 2,941
  • 3
  • 21
  • 27
AR89
  • 2,906
  • 6
  • 25
  • 42
  • 1
    Tail recursion means the last line in the method will be the recursive call. Keep that in mind when designing these. – corsiKa Sep 30 '11 at 18:32
  • According to your requirements, the above does not fit since you have 3 instance variables: `number, count, average`. So do you need help fixing this to use recursion instead of the instance variables or are you just interested in the std dev? – John B Sep 30 '11 at 18:33
  • Do you know of a calculation that can do a running std dev? If you don't respond to questions how can we help you. – John B Sep 30 '11 at 18:57
  • @Jhon B The above does fit, for instance variables I meant variables allocated outside the method, that could e used even without the recursion. My professor suggested us to use Objects to solve the problem. – AR89 Oct 01 '11 at 07:55
  • @AR89 I am not really clear on your requirements. The `NumberWithCounterAndAverage` class has instance variables but you said "No instance variables allowed" which suggests that you are only allowed method scope variables. At any rate, my suggestion will work without any instance variables and so therefore you don't run a risk either way. – John B Oct 01 '11 at 18:47

3 Answers3

1

I think the idea you should be going for is to have a function which takes as arguments the current count, sum, average, etc that is needed for the calculation. This would support your requirement for no instance variables unlike what you have above.

The first call to this method would pass all zeros. Each subsequent call would read in one value and if not 0 call itself with the updated values. If zero, do the final calculation and output the results.

The answer is at this post: How to efficiently calculate a running standard deviation?

With this calculation: have the method take the sum_x, sum_x2 and count. (sum_x is the sum of the elements, sum_x2 is the sum of the squares). In the iteration where you receive 0 the results are:

sum = sum_x
average = sum_x / count
stdev = sqrt((sum_x2 / count) - (average * average)) 
Community
  • 1
  • 1
John B
  • 30,460
  • 6
  • 67
  • 92
1

To compute the standard deviation, you must, for each amount entered, square the difference between that amount and the average. You can't know the average until all elements are entered. So you'll have to compute the standard deviation while returning from the functions.

To compute the standard deviation, you will need the count, the average, and an accumulator for the sum of the squared differences. This would be your "NumberWithCounterAndAverage" class.

During the initial calls that build the stack, I would input one number per recursion, and pass count and sum variables as parameters.

Jeff Grigg
  • 934
  • 7
  • 7
  • 1
    This means, that at the top of the stack (when the input entered is 0) I should already have the total sum, the average, and the count. And when it comes back it should calculate the difference between the amount entered in each method of the stack and sum it, to the one previously returned. Should it work this way? – AR89 Oct 01 '11 at 08:10
  • You could do it this way, but the method would need to return more than one value: sum, count, std_dev sum. If you are allowed to create a class with instance variables to do this, then this will work. However, I believe my suggested solution is simpler. – John B Oct 01 '11 at 18:52
0

I have solved the assignment, thanks to all of you. Here is the solution, I have added the double standardDeviation, to the object in the code above

 public static NumberWithCounterAndAverage calculateStandardDeviation(){
    Scanner sc= new Scanner(System.in);
    NumberWithCounterAndAverage nccem= new NumberWithCounterAndAverage();
    System.out.println("Insert number");
    int x= sc.nextInt();
    int counter=1;
    int sum=x;
    nccem=calculateStandardDeviation(sum, counter);

    int partialDeviationSum=((x-nccem.getAverage())*(x-nccem.getAverage()));
    nccem.setDeviazioneStandard(partialDeviationSum+nccem.getStandardDeviation());

    double standardDeviation= Math.sqrt(nccem.getStandardDeviation());
    nccem.setStandardDeviation(standardDeviation);

    return nccem;
}
public static NumberWithCounterAndAverage calculateStandardDeviation(int sum, int counter){
    Scanner sc= new Scanner(System.in);
    NumberWithCounterAndAverage nccem= new NumberWithCounterAndAverage();
    System.out.println("Insert number");
    int x= sc.nextInt();
    int partialSum=0, partialCounter=0;
    if(x!=0){
        partialSum= x+sum;
        partialCounter=1+counter;
        nccem=calculateStandardDeviation(partialSum, partialCounter);
    }
    if(x==0){//I am at the top of the stack, I calculate the average and i go down
        nccem.setAverage(sum/counter);
    }
    if(x!=0){
        int sumPartialDeviation=((x-nccem.getAverage())*(x-nccem.getAverage()));
        nccem.setStandardDeviation(sumPartialDeviation+nccem.getStandardDeviation());
    }

    return nccem;
}
AR89
  • 2,906
  • 6
  • 25
  • 42
  • Why do you have two `if (x!=0)` conditions? This is not true tails recursion since the last line of the method is not the recursive call. Is that not part of the requirement? – John B Oct 01 '11 at 18:55
  • Let's see what the instructor thinks of it. (I did not notice the "tail recursion" part of the original post until now. That would make it more challenging! ;-) – Jeff Grigg Oct 02 '11 at 13:09