How do I create a loop to generate min, max, avg for 2 array lists, i have only generated the min, max and avg with sum for single array lists so far.
These are the 2 arrays User[] & Withdrawals[]:
User, Withdrawals
1 , 90.00
2 , 85.00
4 , 75.00
5 , 65.00
2 , 40.00
1 , 80.00
3 , 50.00
5 , 85.00
4 , 80.00
1 , 70.00
size = 10
This is what i have tried, as i have no clue about 2 arrays interdependent:
double min = 0.0;
double max = 0.0;
double sum = 0.0;
double avg = 0.0;
for(int i = 0; i <size; i++){
.
.
for(int j = 0; j < Withdrawals.length; j++){
if(Withdrawals[User[i]] > max){
max = Withdrawals[j];
}
if(Withdrawals[User[i]] < min){
min = Withdrawals[j];
}
}
sum += Withdrawals[j];
avg = sum/size;
}
how do i print the min, max, avg from the no of withdrawals per user ? :S
I have already counted the number of withdrawals per user.
Conditions are: create everything from scratch instead of using available library features of Java.
Divide and conquer :)
Yes, I know that is a term used for an algorithm technique, in this case what I mean is... work with small parts.
First having the min, max, avg for a simple array:
double[] values = {2,3,4,5,6,7};
double min = values[0];
double max = values[0];
double sum = 0;
for (double value : values) {
min = Math.min(value, min);
max = Math.max(value, max);
sum += value;
}
double avg = sum / values.length;
System.out.println("Min: " + min);
System.out.println("Max: " + max);
System.out.println("Avg: " + avg);
Note: Since you can't use Java libraries for your assignment, is easy to do your own versions of the min/max functions (read the Math JavaDoc)
Now you can encapsulate this code in a function, you can start by returning another array:
static double[] minMaxAvg(double[] values) {
double min = values[0];
double max = values[0];
double sum = 0;
for (double value : values) {
min = Math.min(value, min);
max = Math.max(value, max);
sum += value;
}
double avg = sum / values.length;
return new double[] {min, max, avg};
}
public static void main(String[] args) {
double[] values = {2,3,4,5,6,7};
double[] info = minMaxAvg(values);
System.out.println("Min: " + info[0]);
System.out.println("Max: " + info[1]);
System.out.println("Avg: " + info[2]);
}
Using an array is a little bit ugly to read, so is better if you create a class to hold the min, max, avg. So lets refactor the code a little bit:
class ValueSummary {
final double min;
final double max;
final double avg;
static ValueSummary createFor(double[] values) {
double min = values[0];
double max = values[0];
double sum = 0;
for (double value : values) {
min = Math.min(value, min);
max = Math.max(value, max);
sum += value;
}
double avg = sum / values.length;
return new ValueSummary(min, max, avg);
}
ValueSummary(double min, double max, double avg) {
this.min = min;
this.max = max;
this.avg = avg;
}
public String toString() {
return "Min: " + min + "\nMax: " + max +"\nAvg: " + avg;
}
}
public static void main(String[] args) {
double[] values = {2,3,4,5,6,7};
ValueSummary info = ValueSummary.createFor(values);
System.out.println(info);
}
You don't specify it in your question, but I assume that you have an array for each user (maybe each withdrawals is another array).
Now that you have the bottom parts, we can switch to a top-down thinking.
So your code could be something like this:
for (User aUser : users) {
System.out.println("User: " + aUser);
System.out.println(ValueSummary.createFor(withdrawalsOf(aUser)));
}
Ok, but this is just the idea, you still have the problem to relate aUser with its withdrawals. You have several options here:
Make a "table" User-> Withdrawals, that is what you are trying to do with the two arrays. The User index in the array acts like a "user id". When you learn about Map you will see that you can use a better representation for the index.
Having a Map or array is just an optimization, of the relationship User->Withdrawls, but you can represent that relationship with an object (ie UserWithdrawls)
Option 1:
static class User {
final String name;
public User(String s) { name = s; }
}
public static void main(String[] args) {
User[] users = { new User("John"), new User("Doe")};
double[][] withdrawals = {
new double[] { 1, 2, 3}, new double[] { 10,22, 30}
};
for (int i = 0; i < users.length; i++) {
System.out.println("User: " + users[i].name);
System.out.println(ValueSummary.createFor(withdrawals[i]));
}
}
Option 2:
static class User {
final String name;
public User(String s) { name = s; }
}
static class UserWithdrawls {
final User user;
final double[] withdrawals;
final ValueSummary summary;
UserWithdrawls(User user, double[] withdrawals) {
this.user = user;
this.withdrawals = withdrawals;
this.summary = ValueSummary.createFor(withdrawals);
}
}
public static void main(String[] args) {
UserWithdrawls[] userWithdrawls = {
new UserWithdrawls(new User("John"), new double[] { 1, 2, 3}),
new UserWithdrawls(new User("Doe"), new double[] { 10, 22, 30})
};
for (UserWithdrawls uw : userWithdrawls) {
System.out.println("User: " + uw.user.name);
System.out.println(uw.summary);
}
}
Additional notes: If you are studying Computer Science, you'll learn in the future that the loop to calculate max, min, avg has a complexity of O(n). If the values array is fully loaded in memory, doing the max/min/avg in three different functions (thus reading the array 3 times) is still an algorithm of O(n) order with a bigger constant. With the power of today's computers the constant is so small, that most of the time you'll not get any gain from calculating min/max/avg in the same loop. In contrast you can gain code readability, for example in Groovy the minMaxAvg code could be written like this:
def values = [2,3,4,5,6,7];
println values.min()
println values.max()
println values.sum() / values.size()
Quick n Dirty: Use a second for loop for the second array, but do not reinitialize the min, max etc again.
Cleaner would be to make a class to hold the min, max etc, and a method that is passed this result object and an array. The method then scans the array and updates the result objects min, max etc. Call the method for each array.
Why don't you try to look at the code of Descriptive Statistics in the Commons Math library? Or better, use it instead of reinvent the wheel?
DescriptiveStatistics de = new DescriptiveStatistics();
de.addValue(..) // Your values
// Add more values
Double max = de.getMax();
Double min = de.getMin();
Double avg = de.getSum() / de.getN(); // or de.getMean();
And use an instance of DescriptiveStatistics for every array.
I think it would be better if you stored the details for each user in a seperate data structure like the following class named UserWithdrawals.
public class Program1{
public static class UserWithdrawals{
private LinkedList<Double> withdrawals=new LinkedList<>();
public void add(Double amt){
this.withdrawals.add(amt);
}
public Double getMinimum(){
Double min=this.withdrawals.get(0);
for(Double amt:this.withdrawals)
if(amt.compareTo(min)<0) min=amt;
return min;
}
public Double getMaximum(){
Double max=this.withdrawals.get(0);
for(Double amt:this.withdrawals)
if(amt.compareTo(max)>0) max=amt;
return max;
}
public Double getAverage(){
Double sum=new Double(0);
for(Double amt:this.withdrawals)
sum+=amt;
return sum/this.withdrawals.size();
//this method will fail if the withdrawals list is updated during the iteration
}
/*You can also combine the three into a single method and return an array of Double object coz the iteration is same.*/
}
/*now you iterate over your two array lists (This wont work if the two array lists - 'Users' and 'Withdrawals' are of different size) and store the withdrawal data associated with a user in the corresponding map value - Maps or Associative arrays are a very basic data structure so your professor should not have any problems with this*/
private HashMap<Integer,UserWithdrawals> withdrawals_map=new HashMap<>();
public Program1(ArrayList<Integer> Users, ArrayList<Double> Withdrawals){
for(int i=0;i<Users.size();i++){
Integer user_no=Users.get(i);
Double withdrawal_amt=Withdrawals.get(i);
if(this.withdrawals_map.get(user_no)==null){
this.withdrawals_map.put(user_no,new UserWithdrawals());
}
this.withdrawals_map.get(user_no).add(withdrawal_amt);
}
}
public UserWithdrawals getUserWithdrawalsData(Integer user_no){
return this.withdrawals_map.get(user_no);
}
}
Sort the 2D array in O(log(n)) based on 1st column, by using c++ STL Sort function.
Traverse in O(n) to calculate the average and update MaxAverage.
// Driver function to sort the 2D vector
// on basis of a particular column
bool sortcol( const vector<int>& v1, const vector<int>& v2 ) {
return v1[0] < v2[0];
}
void sortMatrix()
{
// Initializing 2D vector "vect" with
// values S_ID,MARKS
vector< vector<int> > vect{{1,85}, {2,90}, {1,87}, {1,99}, {3,70}};
// Number of rows
int m = vect.size();
// Number of columns
int n = vect[0].size();
// Use of "sort()" for sorting on basis
// of 1st column
sort(vect.begin(), vect.end(),sortcol);
float maxAverage=-1;
int id=1; // assuming it starts from 1.
float sum=0;
int s=0; // size of marks per student to calculate average
for( int i=0; i<m; i++ )
{
sum+=vect[i][1];
s=s+1;
if( i+1!= m && vect[i+1][0] != vect[i][0] ){// gotten all the marks of this student
maxAverage = maxAverage>sum/s? maxAverage:sum/s;
id = vect[i][0];
s=0;
sum=0;
}
}
cout<<"ID: "<<id<<"\tValue: "<<maxAverage<<endl;
}
Output:
ID: 2 Value: 90.3333
Related
I'm working on a project that prompts the user to create and fill an array with integers, then displays the mean, mode, median, and standard deviation of that array. It starts by asking the user what the size of the array will be, to which the number entered will declare and initialize the array. The program will then iterate several times asking the user to declare an integer value, and each value will be stored into the array until the array is filled. The program will then print the contents of the array, as well as the mean, mode, median, and standard deviation.
I have a code that seems to meet all these requirements. However, one thing I am struggling on is the mode. While it does print out the most repeated number in the array, it doesn't take into account multiple modes with the same number of repetitions, nor does it take into account what will happen if there is no mode.
Right now, if two numbers are entered twice each, the mode displayed is the first number to be repeated more than once. For example, if I have an array size of 10 integers, and the integers I enter are 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, it will print out "2.0" for the mode instead of printing both "2.0" and "3.0." If there is no mode, it simply enters the number first entered, rather than saying "None."
What would be the best course of action to go about accomplishing this?
Here is my code:
import java.util.*;
public class ArrayStatistics {
public static void main(String[] args) {
double total = 0;
Scanner input = new Scanner(System.in);
System.out.print("Enter the size of your array >> ");
int size = input.nextInt();
double[] myArray = new double[size];
System.out.print("Enter the integer values >> ");
for (int i=0; i<size; i++) {
myArray[i] = input.nextInt();
}
System.out.println("\nIntegers:");
for (int i=0; i<size; i++) {
System.out.println(myArray[i]);
}
double mean = calculateMean(myArray);
System.out.println("\nMean: " + mean);
double mode = calculateMode(myArray);
System.out.println("Mode: " + mode);
double median = calculateMedian(myArray);
System.out.println("Median: " + median);
double SD = calculateSD(myArray);
System.out.format("Standard Deviation: %.6f", SD);
}
public static double calculateMean(double myArray[]) {
int sum = 0;
for(int i = 0; i<myArray.length; i++) {
sum = (int) (sum + myArray[i]);
}
double mean = ((double) sum) / (double)myArray.length;
return mean;
}
public static double calculateMode(double myArray[]) {
int modeCount = 0;
int mode = 0;
int currCount = 0;
for(double candidateMode : myArray) {
currCount = 0;
for(double element : myArray) {
if(candidateMode == element) {
currCount++;
}
}
if(currCount > modeCount) {
modeCount = currCount;
mode = (int) candidateMode;
}
}
return mode;
}
public static double calculateMedian(double myArray[]) {
Arrays.sort(myArray);
int val = myArray.length/2;
double median = ((myArray[val]+myArray[val-1])/2.0);
return median;
}
public static double calculateSD(double myArray[]) {
double sum = 0.0;
double standardDeviation = 0.0;
int length = myArray.length;
for(double num : myArray) {
sum += num;
}
double mean = sum/length;
for(double num : myArray) {
standardDeviation += Math.pow(num - mean, 2);
}
return Math.sqrt(standardDeviation/length);
}
First the code, then the explanations.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;
public class ArrayStatistics {
public static void main(String[] args) {
int total = 0;
Scanner input = new Scanner(System.in);
System.out.print("Enter the size of your array >> ");
int size = input.nextInt();
int[] myArray = new int[size];
Map<Integer, Integer> frequencies = new HashMap<>();
System.out.print("Enter the integer values >> ");
for (int i = 0; i < size; i++) {
myArray[i] = input.nextInt();
if (frequencies.containsKey(myArray[i])) {
int frequency = frequencies.get(myArray[i]);
frequencies.put(myArray[i], frequency + 1);
}
else {
frequencies.put(myArray[i], 1);
}
total += myArray[i];
}
System.out.println("\nIntegers:");
for (int i = 0; i < size; i++) {
System.out.println(myArray[i]);
}
double mean = calculateMean(size, total);
System.out.println("\nMean: " + mean);
List<Integer> mode = calculateMode(frequencies);
System.out.println("Mode: " + mode);
double median = calculateMedian(myArray);
System.out.println("Median: " + median);
double stdDev = calculateSD(mean, total, size, myArray);
System.out.format("Standard Deviation: %.6f", stdDev);
}
public static double calculateMean(int count, int total) {
double mean = ((double) total) / count;
return mean;
}
public static List<Integer> calculateMode(Map<Integer, Integer> frequencies) {
Map<Integer, Integer> sorted = frequencies.entrySet()
.stream()
.sorted((e1, e2) -> e2.getValue() - e1.getValue())
.collect(Collectors.toMap(e -> e.getKey(),
e -> e.getValue(),
(i1, i2) -> i1,
LinkedHashMap::new));
Iterator<Integer> iterator = sorted.keySet().iterator();
Integer first = iterator.next();
Integer val = sorted.get(first);
List<Integer> modes = new ArrayList<>();
if (val > 1) {
modes.add(first);
while (iterator.hasNext()) {
Integer next = iterator.next();
Integer nextVal = sorted.get(next);
if (nextVal.equals(val)) {
modes.add(next);
}
else {
break;
}
}
}
return modes;
}
public static double calculateMedian(int myArray[]) {
Arrays.sort(myArray);
int val = myArray.length / 2;
double median = ((myArray[val] + myArray[val - 1]) / 2.0);
return median;
}
public static double calculateSD(double mean, int sum, int length, int[] myArray) {
double standardDeviation = 0.0;
for (double num : myArray) {
standardDeviation += Math.pow(num - mean, 2);
}
return Math.sqrt(standardDeviation / length);
}
}
In order to determine the mode(s), you need to keep track of the occurrences of integers entered into your array. I use a Map to do this. I also calculate the total while entering the integers. I use this total in methods that require it, for example calculateMean. Seems like extra work to recalculate the total each time you need it.
You are dealing with integers, so why declare myArray as array of double? Hence I changed it to array of int.
Your question was how to determine the mode(s). Consequently I refactored method calculatMode. In order to determine the mode(s), you need to interrogate the frequencies, hence the method parameter. Since you claim that there can be zero, one or more than one modes, the method returns a List. First I sort the Map entries according to the value, i.e. the number of occurrences of a particular integer in myArray. I sort the entries in descending order. Then I collect all the sorted entries to a LinkedHashMap since that is a map that stores its entries in the order in which they were added. Hence the first entry in the LinkedHashMap will be the integer with the most occurrences. If the number of occurrences of the first map entry is 1 (one), that means there are no modes (according to this definition that I found):
If no number in the list is repeated, then there is no mode for the list.
In the case of no modes, method calculateMode returns an empty List.
If the number of occurrences of the first entry is more than one, I add the integer to the List. Then I iterate through the remaining map entries and add the integer to the List if its occurrences equals that of the first map entry. As soon as the number of occurrences in an entry does not equal that of the first entry, I exit the while loop. Now List contains all the integers in myArray with the highest number of occurrences.
Here is a sample run (using example data from your question):
Enter the size of your array >> 10
Enter the integer values >> 1 2 2 3 3 4 5 6 7 8
Integers:
1
2
2
3
3
4
5
6
7
8
Mean: 4.1
Mode: [2, 3]
Median: 3.5
Standard Deviation: 2.211334
I need to determine the minimum value after removing the first value.
For instance is these are the numbers 0.5 70 80 90 10
I need to remove 0.5, the determine the minimum value in the remaining numbers. calweightAvg is my focus ...
The final output should be “The weighted average of the numbers is 40, when using the data 0.5 70 80 90 10, where 0.5 is the weight, and the average is computed after dropping the lowest of the rest of the values.”
EDIT: Everything seems to be working, EXCEPT during the final out put. "The weighted average of the numbers is 40.0, when using the data 70.0, 80.0, 90.0, 10.0, where 70.0 (should be 0.5) is the weight, and the average is computed after dropping the lowest of the rest of the values."
So the math is right, the output is not.
EDIT: While using a class static double weight=0.5;to establish the weight, if the user were to change the values in the input file, that would not work. How can I change the class?
/*
*
*/
package calcweightedavg;
import java.util.Scanner;
import java.util.ArrayList;
import java.io.File;
import java.io.PrintWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
public class CalcWeightedAvg {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
//System.out.println(System.getProperty("user.dir"));
ArrayList<Double> inputValues = getData(); // User entered integers.
double weightedAvg = calcWeightedAvg(inputValues); // User entered weight.
printResults(inputValues, weightedAvg); //Weighted average of integers.
}
public class CalcWeightedAvg {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
//System.out.println(System.getProperty("user.dir"));
ArrayList<Double> inputValues = getData(); // User entered integers.
double weightedAvg = calcWeightedAvg(inputValues); // User entered weight.
printResults(inputValues, weightedAvg); //Weighted average of integers.
}
public static ArrayList<Double> getData() throws FileNotFoundException {
// Get input file name.
Scanner console = new Scanner(System.in);
System.out.print("Input File: ");
String inputFileName = console.next();
File inputFile = new File(inputFileName);
//
Scanner in = new Scanner(inputFile);
String inputString = in.nextLine();
//
String[] strArray = inputString.split("\\s+"); //LEFT OFF HERE
// Create arraylist with integers.
ArrayList<Double> doubleArrayList = new ArrayList<>();
for (String strElement : strArray) {
doubleArrayList.add(Double.parseDouble(strElement));
}
in.close();
return doubleArrayList;
}
public static double calcWeightedAvg(ArrayList<Double> inputValues){
//Get and remove weight.
Double weight = inputValues.get(0);
inputValues.remove(0);
//Sum and find min.
double min = Double.MAX_VALUE;
double sum = 0;
for (Double d : inputValues) {
if (d < min) min = d;
sum += d;
}
// Calculate weighted average.
return (sum-min)/(inputValues.size()-1) * weight;
}
public static void printResults(ArrayList<Double> inputValues, double weightedAvg) throws IOException {
Scanner console = new Scanner(System.in);
System.out.print("Output File: ");
String outputFileName = console.next();
PrintWriter out = new PrintWriter(outputFileName);
System.out.println("Your output is in the file " + outputFileName);
out.print("The weighted average of the numbers is " + weightedAvg + ", ");
out.print("when using the data ");
for (int i=0; i<inputValues.size(); i++) {
out.print(inputValues.get(i) + ", ");
}
out.print("\n where " + inputValues.get(0) + " is the weight, ");
out.print("and the average is computed after dropping the lowest of the rest of the values.\n");
out.close();
}
}
to do this task in a complexity of O(n) isn't a hard task.
you can use ArrayList's .get(0) to Save weight in a temp variable, then use .remove(0) function which removes the first value (in this case 0.5)
then you should use a For Each loop for (Double d : list) to sum AND find the minimal value
afterwards subtract the minimum value from the sum. and apply weight to the sum (in this case you'll end up with 240*0.5 = 120; 120\3 = 40;
finally, you can use ArrayList's .size()-1 function to determine the divisor.
The problem in your code:
in your implementation you've removed the weight item from list. then multiplied by the first item in the list even though it's no longer the weight:
return (sum-min)/(inputValues.size()-1) * inputValues.get(0);
your calculation than was: ((70+80+90+10)-10)/(4-1) * (70) = 5600
if(inputValues.size() <= 1){
inputValues.remove(0);
}
this size safeguard will not remove weight from the list. perhaps you've meant to use >=1
even if that was your intention this will not result in a correct computation of your algorithm in the edge cases where size==0\1\2 I would recommend that you re-think this.
the full steps that need to be taken in abstract code:
ArrayList<Double> list = new ArrayList();
// get and remove weight
Double weight = list.get(0);
list.remove(0);
// sum and find min
double min=Double.MAX_VALUE;
double sum=0;
for (Double d : list) {
if (d<min) min = d;
sum+=d;
}
// subtract min value from sum
sum-=min;
// apply weight
sum*=weight;
// calc weighted avg
double avg = sum/list.size()-1;
// viola!
do take notice that you can now safely add weight back into the array list after its use via ArrayList's .add(int index, T value) function. also, the code is very abstract and safeguards regarding size should be implemented.
Regarding your Edit:
it appears you're outputting the wrong variable.
out.print("\n where " + inputValues.get(0) + " is the weight, ");
the weight variable was already removed from the list at this stage, so the first item in the list is indeed 70. either add back the weight variable into the list after you've computed the result or save it in a class variable and input it directly.
following are the implementation of both solutions. you should only use one of them not both.
1) add weight back into list solution:
change this function to add weight back to list:
public static double calcWeightedAvg(ArrayList<Double> inputValues){
//Get and remove weight.
Double weight = inputValues.get(0);
inputValues.remove(0);
//Sum and find min.
double min = Double.MAX_VALUE;
double sum = 0;
for (Double d : inputValues) {
if (d < min) min = d;
sum += d;
}
// Calculate weighted average.
double returnVal = (sum-min)/(inputValues.size()-1) * weight;
// add weight back to list
inputValues.add(0,weight);
return returnVal;
}
2) class variable solution:
change for class:
public class CalcWeightedAvg {
static double weight=0;
//...
}
change for function:
public static double calcWeightedAvg(ArrayList<Double> inputValues){
//Get and remove weight.
weight = inputValues.get(0); // changed to class variable
//...
}
change for output:
out.print("\n where " + weight + " is the weight, ");
Since you're using an ArrayList, this should be a piece of cake.
To remove a value from an ArrayList, just find the index of the value and call
myList.remove(index);
If 0.5 is the first element in the list, remove it with
inputValues.remove(0);
If you want to find the minimum value in an ArrayList of doubles, just use this algorithm to find both the minimum value and its index:
double minVal = Double.MAX_VALUE;
int minIndex = -1;
for(int i = 0; i < myList.size(); i++) {
if(myList.get(i) < minVal) {
minVal = myList.get(i);
minIndex = i;
}
}
Hope this helps!
If you want to remove the first element from ArrayList and calculate the minimum in the remaining you should do:
if(inputValues.size() <= 1) //no point in calculation of one element
return;
inputValues.remove(0);
double min = inputValues.get(0);
for (int i = 1; i < inputValues.size(); i++) {
if (inputValues.get(i) < min)
min = inputValues.get(i);
}
I am a little unclear about your goal here. If you are required to make frequent calls to check the minimum value, a min heap would be a very good choice.
A min heap has the property that it offers constant time access to the minimum value. This [implementation] uses an ArrayList. So, you can add to the ArrayList using the add() method, and minValue() gives constant time access to the minimum value of the list since it ensures that the minimum value is always at index 0. The list is modified accordingly when the least value is removed, or a new value is added (called heapify).
I am not adding any code here since the link should make that part clear. If you would like some clarification, I would be more than glad to be of help.
Edit.
public class HelloWorld {
private static ArrayList<Double> values;
private static Double sum = 0.0D;
/**
* Identifies the minimum value stored in the heap
* #return the minimum value
*/
public static Double minValue() {
if (values.size() == 0) {
throw new NoSuchElementException();
}
return values.get(0);
}
/**
* Adds a new value to the heap.
* #param newValue the value to be added
*/
public static void add(Double newValue) {
values.add(newValue);
int pos = values.size()-1;
while (pos > 0) {
if (newValue.compareTo(values.get((pos-1)/2)) < 0) {
values.set(pos, values.get((pos-1)/2));
pos = (pos-1)/2;
}
else {
break;
}
}
values.set(pos, newValue);
// update global sum
sum += newValue;
}
/**
* Removes the minimum value from the heap.
*/
public static void remove() {
Double newValue = values.remove(values.size()-1);
int pos = 0;
if (values.size() > 0) {
while (2*pos+1 < values.size()) {
int minChild = 2*pos+1;
if (2*pos+2 < values.size() &&
values.get(2*pos+2).compareTo(values.get(2*pos+1)) < 0) {
minChild = 2*pos+2;
}
if (newValue.compareTo(values.get(minChild)) > 0) {
values.set(pos, values.get(minChild));
pos = minChild;
}
else {
break;
}
}
values.set(pos, newValue);
}
// update global sum
sum -= newValue;
}
/**
* NEEDS EDIT Computes the average of the list, leaving out the minimum value.
* #param newValue the value to be added
*/
public static double calcWeightedAvg() {
double minValue = minValue();
// the running total of the sum took this into account
// so, we have to remove this from the sum to get the effective sum
double effectiveSum = (sum - minValue);
return effectiveSum * minValue;
}
public static void main(String []args) {
values = new ArrayList<Double>();
// add values to the arraylist -> order is intentionally ruined
double[] arr = new double[]{10,70,90,80,0.5};
for(double val: arr)
add(val);
System.out.println("Present minimum in the list: " + minValue()); // 0.5
System.out.println("CalcWeightedAvg: " + calcWeightedAvg()); // 125.0
}
}
I'm trying to find the average of integers elements in an array using recursion. I know how to do it using loops, but I have to do it by recursion for my assignment, so what I tried to do is to find the sum of elements using recursion and then divide the sum by the length of the array. I wrote this code but it gives me a wrong result:
public int findAvg(int a[], int n)
{
int sum,avg;
if(n==1)
{
sum=a[0];
return sum;
}
else
{
sum=a[n-1]+findAvg(a,n-1);
}
avg = sum/n;
return avg;}
The calling of findAvg method in main class:
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Recursive r = new Recursive ();
int integersArr [] = {1,2,3,4,5};
int max = r.findMax(integersArr,integersArr.length );
int avg = r.findAvg(integersArr, integersArr.length);
System.out.println("Maximum element = "+ max);
System.out.println("Average value of elements = "+ avg);
}
}
The console output:
Average value of elements = 1
First of all sum=a[n-1]+findAvg(a,n-1); is wrong, since if findAvg(a,n-1) returns the correct average for the first (n-1) elements, the sum should be a[n-1] + (n-1) * findAvg(a,n-1).
Second of all, you are losing precision when dividing integers in avg = sum/n; Consider using doubles.
First of all average of integers can be floating point. So make the return type of your function to float or double.
Now,
If you have set of n numbers with average of x and you want to add one more number to the set (say b). New average will be ((n * x) + b) / (n + 1). Use the same trick in your code.
public float findAvg(int a[], int n)
{
float sum,avg;
if(n==1)
{
sum=a[0];
}
else
{
// Calculate sum of n-1 numbers = (n-1) * (avg of n-1 numbers)
// and add nth number to it ( i.e. a[n-1])
sum= a[n-1]+ (n-1) * findAvg(a,n-1);
}
avg = sum/n;
return avg;
}
public double average(int y[], int i) {
double result;
result = (double)y[i] / (double)y.length;
if (i == 0)
return result;
else
return result + average(y, i-1);
}
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Recursive r = new Recursive ();
int integersArr [] = {1,2,3,4,5};
int max = r.findMax(integersArr,integersArr.length );
int avg = r.findAvg(integersArr, integersArr.length);
System.out.println("Maximum element = "+ max);
System.out.println("Average value of elements = "+ avg);
}
}
Sorry guys, I will reiterate the question. I have an array with 12 elements:
1.6, 2.1, 1.7, 3.9, 3.7, 3.9, 2.9, 4.3, 2.4, 3.7
I want to get the largest value in this array. Question is how can I invoke the method from my main class to an object created in my driver class?
//MAIN CLASS
import java.util.Scanner;
public class Rainfall
{
private double total = 0;
private double average;
private double max;
private double smallest;
private double rain[];
Scanner scan = new Scanner(System.in);
public Rainfall(double...rainfall)
{
double[] rain = {1.6 , 2.1, 1.7, 3.9, 3.7, 3.9, 2.9, 4.3, 2.4, 3.7};
}
public double getTotal()
{
total = 0;
for(int i = 0; i < 12; i++)
{
total = total + rain[i];
}
System.out.println("The total rainfall for the year is: " + total);
return total;
}
public double getAverage()
{
average = total/12;
System.out.println("The average monthly rainfall is: " + average);
return average;
}
public double getMostRain()
{
double max = 0;
int maxind = 0;
for(int i = 0; i < 12; i++)
{
if (rain[i] > max)
{
max = rain[i];
maxind = i;
}
}
System.out.println("The largest amout of rainfall was: " + max +
"inches in month" + (maxind + 1));
return max;
}
public double getLeastRain()
{
double smallest = Double.MAX_VALUE;
int smallind = 0;
for(int n = 0; n < 12; n++)
{
if (rain[n] < smallest)
{
smallest = rain[n];
smallind = n;
}
}
System.out.println("The smallest amout of rainfall was" + smallest +
"inches in month " + (smallind + 1));
return smallest;
}
}
//DriverClass
public class RainfallDriver {
public static void main(String[] args) {
double[] list = {1.6 , 2.1, 1.7, 3.9, 3.7, 3.9, 2.9, 4.3, 2.4, 3.7};
//Counts the total and average from the elements in the array
double total = 0;
double average =0;
for (double element : list)
total += element;
average = total/12;
System.out.println("Total: " + total);
System.out.println("Smallest: " +rain.getLeastRain()); //How can I call the method?
System.out.println("Largest: " + rain.getMostRain()); //How can I call the method?
System.out.println("Average: " + average);
}
}
If you can use Java 8, the new Lambda Expressions solve the problem in a nice one-liner:
double max = Arrays.stream(rain).max().getAsDouble();
The reason why you need to call the trailing getAsDouble() method is because the max() method returns an OptionalDouble, because Java needs a way of handling the possibility that the rain array may be empty.
Likewise, your other methods can be implemented like:
double min = Arrays.stream(rain).min().getAsDouble();
double average = Arrays.stream(rain).average().getAsDouble();
or together:
DoubleStream rainStream = Arrays.stream(rain);
double max = rainStream.max().getAsDouble();
double min = rainStream.min().getAsDouble();
double average = rainSteam.average().getAsDouble();
The way I see it, you don't quite understand what OOP is, and how to use it:
You are writing a class called Rainfall, and you are (correctly) declaring its members (attributes)... but you are not initializing them! Your constructor declares a local variable with the same name as one of your class's attributes, but doesn't use it anywhere.
If what I am seeing is right, then what you want is something like this:
public class Rainfall {
private double[] rain;
/*
It is a good idea to make the attributes private, and then access them
through methods (getters to get the values, setters to change the values)
*/
// more attributes here
public Rainfall(double[] rain) {
this.rain = rain; // THIS IS THE WAY how you initialize an attribute
}
public double getRain() {
/*
Remember what I said about getters? This is an example
*/
return rain;
}
public void setRain(double[] rain) {
/*
Remember what I said about setters? This is an example
*/
this.rain = rain;
}
// More code...
}
And now, if you want to use this array in another class, you can write something like this:
public class SomeOtherClass {
// Some code
public static void main(String[] args) {
Rainfall rainfall = new Rainfall(); // Declare and instantiate the object
double[] rain = rainfall.getRain(); // Retrieve the value of the attribute
/*
And now... how to get the max value? Here's an example
*/
double maxVal = Double.NEGATIVE_INFINITY;
for(double x : rain) {
if(x > maxVal)
maxVal = x;
}
// More code
}
}
I really recommend you take a good read to The Java Tutorials.
I'm not sure what you're asking... But something like this would work to find the largest element of the rain array.
int largestNum = 0;
for ( int i = 0; i < 12; i++ )
{
if ( rain [ i ] >= largestNum )
{
largestNum = rain[ i ];
}
}
I thought I had this figure out, and I was pretty confident it was going to work. Unfortunately, it did not.
The code below is supposed to return the average, the number of values entered and then calculate the std Var. I get it to return the average and count, but the std var result is off. Using the values 5, 6, 8 and 9 I am supposed to get a result of std var 1.83, I am getting something way off 7.17.
I know my error is in the way I am calculating the std Dev, but I was pretty sure I was doing it right.
Here is my code:
/**
This class is used to calculate the average and standard deviation
of a data set.
*/
public class DataSet{
private double sum;
private double sumSquare;
private int counter;
/**Constructs a DataSet object to hold the
* total number of inputs, sum and square
*/
public DataSet(){
sum = 0;
sumSquare = 0;
counter = 0;
}
/**Adds a value to this data set
* #param x the input value
*/
public void add(double x){
sum = sum + x;
sumSquare = sumSquare + x * x;
counter++;
}
/**Calculate average of dataset
* #return average, the average of the set
*/
public double getAverage(){
double avg = sum / counter;
return avg;
}
/**Get the total inputs values
* #return n, the total number of inputs
*/
public int getCount(){
return counter;
}
public double getStandardDeviation(){
double sqr = sumSquare / counter;
double stdDev = Math.sqrt(sqr);
return stdDev;
}
}
Here is my runner program:
import java.util.Scanner;
class DataSetRunner
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
DataSet data = new DataSet();
boolean done = false;
while (!done)
{
System.out.println("Enter value, Q to quit: ");
String userInput = input.next();
if (userInput.equalsIgnoreCase("Q"))
done = true;
else
{
double x = Double.parseDouble(userInput);
data.add(x);
}
}
System.out.println("Average = " + data.getAverage());
System.out.println("Count = " + data.getCount());
System.out.println("The Standard Deviation is = " + data.getStandardDeviation());
}
Your calculation is incorrect.
Standard deviation is based on the sum of the squares of the difference to the mean.
You are simply summing the squares of the data values.
You must first calculate the mean (ie the average), then once you know that you can calculate the standard deviation using this value.
The correct procedure is (quoting from wikipedia):
To calculate the population standard deviation, first compute the difference of each data point from the mean, and square the result of each:
Next, compute the average of these values, and take the square root:
Basically, you can't calculate the standard deviation "as you go".