Passing array to get mean median and mode in java - java

I am trying to use java to pass an array to get the mean, median,mode , max an min in java. I am currently having an issue passing the array to a function and return its value so i can output the results. I believe i have the loops correct to solve the mean median and mode but i cannot get them to send and receive as wanted. How can I pass the array and send back the values needed?
UPDATE: i have updated the code it will compile and i can input the number of years but i get several errors following after that. it is also not printing the outputs
Exception in thread "main" java.util.UnknownFormatConversionException: Conversion = 'i'
at java.util.Formatter$FormatSpecifier.conversion(Formatter.java:2646)
at java.util.Formatter$FormatSpecifier.(Formatter.java:2675)
at java.util.Formatter.parse(Formatter.java:2528)
at java.util.Formatter.format(Formatter.java:2469)
at java.io.PrintStream.format(PrintStream.java:970)
at java.io.PrintStream.printf(PrintStream.java:871)
at la5cs1110_woodspl_03.pkg17.pkg2016.La5cs1110_WoodsPl_03172016.main(La5cs1110_WoodsPl_03172016.java:56)
Java Result: 1
public static void main(String[] args) {
int i;
List<Double> hArray = new ArrayList<>();
int nYears = 0, y = 0;
double rMax = 0.00,rMin = 100.00;
//get input check if between 1-80
while(y == 0){
String userData = JOptionPane.showInputDialog
("Enter number of years");
nYears = Integer.parseInt(userData);
if (nYears > 1 && nYears <= 80 )
y = 1;
}
y = 0;
while(y <= nYears){
for(i = 0; i < 12; i++){
Random rand = new Random();
double rNum = rand.nextFloat() * (rMax - rMin) + rMin;
hArray.add(rNum);
}
double mean = getMean (hArray);
double median = getMedian (hArray);
double mode = getMode (hArray);
double max = getMaxValue(hArray);
double min = getMinValue (hArray);
System.out.printf("In year %i the Mean = %d , mode = %d, median = %d," +
" max = %d, min = %d", y , mean, median, mode, max, min);
y++;
}
}
private static double getMean(List<Double> hArray) {
double sum = 0;
for (int i = 0; i < hArray.size(); i++) {
sum += hArray.get(i);
}
return sum / hArray.size();
}
//Median
private static double getMedian(List<Double> hArray) {
int middle = hArray.size()/2;
if (hArray.size() %2 == 1) {
return hArray.get(middle);
} else {
return (hArray.get(middle-1) + hArray.get(middle)) / 2.0;
}
}
//Mode
public static double getMode(List<Double> hArray) {
double maxValue = 0, maxCount = 0;
for (int i = 0; i < hArray.size(); ++i) {
int count = 0;
for (int j = 0; j < hArray.size(); ++j) {
if (hArray.get(j) == hArray.get(i)) ++count;
}
if (count > maxCount) {
maxCount = count;
maxValue = hArray.get(i);
}
}
return maxValue;
}
public static double getMaxValue(List<Double> hArray){
double maxValue = hArray.get(0);
for(int i=1;i < hArray.size();i++){
if(hArray.get(i) > maxValue){
maxValue = hArray.get(i);
}
}
return maxValue;
}
public static double getMinValue(List<Double> hArray){
double minValue = hArray.get(0);
for(int i=1;i<hArray.size();i++){
if(hArray.get(i) < minValue){
minValue = hArray.get(i);
}
}
return minValue;
}
}

Your hArray is a List. You should convert it to an array first.
getMean(hArray.toArray)
Check out this.

This does not compile, you try to pass a Double to a method, which expects a double[]. So you have to change the parameter of your methods and use a List and just pass in the hArray (see Tibrogargan answer - i.e., you would have to modify each of your implementations) or do the following:
create a Double[]
Double[] hArray2 = hArray.toArray(new Double[hArray.size()]);
change your methods' signature, so that they expect an Double[]
private static double getMean(Double[] hArray) { ...}
pass hArray2 instead of hArray
double mean = getMean(hArray2);
// ...
That should be it.

Replace the section where you're trying to pass a single element from the array to your statistics functions with calls using the whole array and change the signature of the calls so they take a List<Double> param, not a double[]. Something like this:
double mean = getMean (hArray);
double median = getMedian (hArray);
double mode = getMode (hArray);
double max = getMaxValue(hArray);
double min = getMinValue (hArray);
//Mean
private static double getMean(List<Double> hArray) {
double sum = 0;
for (int i = 0; i < hArray.size(); i++) {
sum += hArray.get(i);
}
return sum / hArray.size();
}
See also: How do you calculate the variance, median, and standard deviation in C++ or Java?
Fix for median:
Copied directly from this above link with some minor modifications to use a List as a param
public Double median(List<Double> list)
{
Double[] array = list.toArray(new Double[list.size()]);
Arrays.sort(data);
if (data.length % 2 == 0)
{
return (data[(data.length / 2) - 1] + data[data.length / 2]) / 2.0;
}
else
{
return data[data.length / 2];
}
}
Fix for mode:
public Double mode(List<Double> list)
{
java.util.TreeMap<Double,Integer> map = new java.util.TreeMap<>();
Double maxVal = null;
int maxCount = 0;
for (Double d : list) {
int count = 0;
if (map.containsKey(d)) {
count = map.get(d) + 1;
} else {
count = 1;
}
map.put(d, count);
if (count > maxCount) {
maxVal = d;
maxCount = count;
}
}
return maxVal;
}

Related

How can I implement java interface to java class

I need help figuring out the following problem :
Create a class Statistics.java to implement the StatisticsI.java. Statistics.java contains ArrayList data to store to data objects of Double type, and properties (attributes): count, min, max, mean, std. The implementation has the following specifications.
addData(Double d) adds data d into the array list, and then update the values of count, min, max, mean, and std, using incremental algorithms, i.e. using exiting existing value to calculate new values, rather than calculating by traversal through the data array.
getCount() returns count.
getMin() returns min.
getMax() returns max.
getMean() returns mean.
getSTD() returns std.
stats() computes the count, min, max, mean, and stddev from the data array in one loop, and then sets the values of the properties.
I have the interface
public interface StatisticsI {
void addData(double d);
int getCount();
double getMin();
double getMax();
double getMean();
double getSTD();
void stats();
}
Here is the code I have so far for the implementation part.
import java.util.ArrayList;
public class Statistics implements StatisticsI {
private ArrayList<Double> data;
private long count;
private double min;
private double max;
private double mean;
private double std;
public Statistics() {
data = new ArrayList<Double>();
count = 0;
min = 0;
max = 0;
mean = 0;
std = 0;
}
public void addData(double d) {
data.add(d);
count += 1;
data.set(data.indexOf(min), min);
data.set(data.indexOf(max), max);
data.set(data.indexOf(mean), mean);
data.set(data.indexOf(std), std);
}
public int getCount() {
count = data.size();
return (int) count;
}
public double getMin() {
return min;
}
public double getMax() {
return max;
}
public double getMean() {
int mean = 0;
for (int i = 0; i < data.size(); i++) {
double currentNum = data.get(i);
mean += currentNum;
}
return mean / data.size();
}
public double getSTD() {
{
double avg = getMean();
double t = 0;
for (int i = 0; i < data.size(); i++) {
double numbers = data.get(i);
double value = Math.pow(numbers - avg, 2);
t += value;
}
double std = (double) t / (double) (data.size());
return Math.sqrt(std);
}
}
public void stats() {
count = data.size();
}
}
I am having trouble with the addData and stats methods and I am not sure if I am doing this correctly and I am trying to figure out how to implement it.
My question is how to implement the interface with what is required in the methods.
Update: How do I call the methods from Statistics
Here is the code for the main class
public static void main(String[] args) {
ArrayList<Double> numList = new ArrayList<Double>();
StatisticsI stats = new Statistics();
Random r = new Random();
for(int i = 1; i <= 10; i++) {
numList.add((double) r.nextInt(10000));
}
double count = stats.getCount();
double min = stats.getMin();
double max = stats.getMax();
double mean = stats.getMean();
double std = stats.getSTD();
System.out.println("The count for the list is:"+ count);
System.out.println("The min for the list is:" + min);
System.out.println("The max for the list is:" + max);
System.out.println("The mean for the list is:" + mean);
System.out.println("The standard deviation for the list is:" + std);
}
}
The problem is I don't get any values for my output, I get :
The count for the list is:0.0
The min for the list is:Infinity
The max for the list is:-Infinity
The mean for the list is:0.0
The standard deviation for the list is:NaN
How do I get my output to work?
in addData(..), use "min = Math.min(min, d)". Math.max also exists, but std and mean are trickier. It's probably easiest to calculate those in the getters by iterating the list.
You can update min, max, mean values immediately in addData.
Update It is also possible to use Welford's algorithm to calculate running deviation.
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
double variance = 0.0;
public void addData(double d) {
data.add(d);
count++;
if (d < min) {
min = d;
} else if (d > max) {
max = d;
}
// fixed calculation of running mean and variance by Welford's algorithm
double new_mean = mean + (d - mean) / count;
variance += count < 2 ? 0.0 : (d - mean) * (d - new_mean);
mean = new_mean;
std = count > 1 ? Math.sqrt(variance / (count - 1)) : 0;
}
Or, you can reset all these values in stats() method using the data list.
There is a convenient way to calculate all stats at once via DoubleSummaryStatistics and Java 8 Stream API:
public void stats() {
DoubleSummaryStatistics stats = data.stream().collect(Collectors.summarizingDouble(x -> x));
count = stats.getCount(); // long value returned instead of `int data.size()`
min = stats.getMin();
max = stats.getMax();
mean = stats.getAverage();
std = this.getSTD();
}
public double getSTD() {
double avg = getMean();
double t = 0.0;
for (double d : data) {
t += Math.pow(avg - d, 2);
}
return Math.sqrt(t / getCount());
}
Loop-based "streamless" calculation of stats including "naive" variance calculation algorithm for std could be as follows:
public void stats() {
count = data.size();
min = Double.POSITIVE_INFINITY;
max = Double.NEGATIVE_INFINITY;
mean = 0.0;
variance = 0.0;
double sum = 0.0;
double sq = 0.0;
int i = 0;
for (double d : data) {
min = Math.min(min, d);
max = Math.max(min, d);
i++;
// calculate running mean as above to use in variance
double new_mean = mean + (d - mean) / i;
variance += i < 2 ? 0 : (d - mean) * (d - new_mean);
mean = new_mean;
sum += d;
sq += d * d;
}
System.out.println("running mean=" + mean);
std = count > 1 ? Math.sqrt((sq - mean * mean / count) / (count - 1)) : 0;
mean = count == 0 ? 0 : sum / count;
}
// override STD getter to remove all calculations
public double getSTD() {
return std;
}
Test
Statistics stats = new Statistics();
stats.addData(17);
stats.addData(19);
stats.addData(24);
System.out.println("after addData()");
System.out.println("mean=" + stats.getMean());
System.out.println("std=" + stats.getSTD());
System.out.println("after addData()");
stats.stats();
System.out.println("mean=" + stats.getMean());
System.out.println("std=" + stats.getSTD());
Output
after addData()
mean=20.0
std=3.605551275463989
after stats()
running mean=20.0
mean=20.0
std=3.605551275463989

Why is my code coming out with the wrong output? Is my insert class wrong?

I have to create classes to be implemented with the main class someone else has and for some reason I am not getting the right outputs, I'm not sure is my calculations are off which I don't think they are or my insert class is wrong.
Expected Output:
Median = 44.5
Mean = 49.300
SD = 30.581
Actual Output:
Median = 0.0
Mean = 0.967
SD = 4.712
public class StatPackage {
int count;
double [] scores;
final int MAX = 500;
StatPackage() {
count = 0;
scores = new double[MAX];
}
public void insert (double value) {
if (count < MAX){
scores[count] = value;
++ count;
}
}
public double Mean () {
double sum = 0;
//For loop for calculating average or mean
for(int i = 0; i < scores.length; i++){
sum += (scores[i]);
count++;
}
double average = sum/count;
return average;
}
public double Median() {
int min;
int tmp;
int size;
for (int i = 0; i < scores.length - 1; i ++)
{
min = i;
for (int pos = i + 1; pos < scores.length; pos ++)
if (scores [pos] < scores [min])
min = pos;
tmp = (int)scores [min];
scores [min] = scores [i];
scores [i] = tmp;
}
double median = 0;
if (scores.length % 2 == 0){
median = (scores[scores.length/2-1] + scores[scores.length/2])/2;
}
else {
median = (scores[((scores.length/2))]);
}
return median;
}
public double Variance () {
double variance = 0;
double sum = 0;
//For loop for getting the variance
for(int i = 0; i < scores.length; i++){
sum += scores[i];
variance += scores[i] * scores[i];
count++;
}
double varianceFinal = ((variance/count)-(sum*sum)/(count*count));
return (varianceFinal);
}
public double StdDev (double variance) {
double sum = 0;
for(int i = 0; i < scores.length; i++){
sum += scores[i];
variance += scores[i] * scores[i];
count++;
}
double varianceFinal = ((variance/count)-(sum*sum)/(count*count));
return Math.sqrt(varianceFinal);
}
}
The length of your scores array is 500, so every time you are using it in a calculation you are running that 500 times. You need to make your loop continuation conditions dependent on the number of values in the array, no the actual length of the array. I would be careful of your variable naming as well, you are using count in two places sometimes and it has global scope! This method stores the number of values in the array in the count variable:
public void insert (double value) {
if (count < MAX){
scores[count] = value;
++count;
}
}
So use the count variable as the loop-continuation condition when you are getting values from the array, like so:
public double mean() {
double sum = 0;
//For loop for calculating average or mean
for(int i = 0; i < count; i++){
sum += (scores[i]);
}
double average = sum / count;
return average;
}
That should help a little, I don't have time to check out your other methods but maybe this will give you a good starting place. I figured out what was happening by inserting print statements in your methods to make sure the values were as expected. It's a helpful thing to do when debugging. Your mean() method with the print statements looks like this:
public double mean() {
double sum = 0;
//For loop for calculating average or mean
for(int i = 0; i < count; i++){
sum += (scores[i]);
}
// print statements for debugging
System.out.println("count is " + count);
System.out.println("sum is " + sum);
double average = sum / count;
return average;
}
Because the solution is easily found by debugging, I will only give you a hint:
The mean of 3, 4 and 5 is 4: (3+4+5)/3, not (3+4+5)/(n*3) where
n is a positive integer.
If you look at your mean and std and divide it by the expected result, you will see it's a rounded number.
Once you find the solution to 1 problem, you will immediately know why the other results are faulty as well =)

How to find the mean, median, mode, and range from an input file?

I need to find the mean, median, mode, and range from an input file.
[input file has the numbers{60,75,53,49,92,71}]
I don't know how to print the calculations from the range out or calculate the mode.
It's pretty bad, I'm very new to Java.
It would be great if anyone could help me with it.
import java.io.*;
import java.util.*;
public class grades {
public static double avg(double[] num) {
double total = 0;
int j = 0;
for (; j < num.length; j++) {
total += num[j];
}
return (total / j);
}
public double getRange(double[] numberList) {
double initMin = numberList[0];
double initMax = numberList[0];
for (int i = 1; i <= numberList.length; i++) {
if (numberList[i] < initMin) initMin = numberList[i];
if (numberList[i] > initMax) initMax = numberList[i];
double range = initMax - initMin;
}
return range;
}
public static void main(String[] args) throws IOException {
double[] num = new double[12];
File inFile = new File("data.txt");
Scanner in = new Scanner(inFile);
for (int i = 0; i < num.length && in.hasNext(); i++) {
num[i] = in.nextDouble();
// System.out.println(num[i]);
}
double avg = grades.avg(num);
System.out.println("Arithmetic Mean = " + avg);
System.out.printf("Median = %.2f%n", grades.getMedian(num));
System.out.println("Range = " + range);
}
public static double getMedian(double[] num) {
int pos = (int) num.length / 2;
return num[pos];
}
}
I don't know how to print the calculations from the range out or calculate the mode.
You have already written a function to calculate the Range. Here is how you can print the Range.
System.out.println("Range = " + getRange(num));
Here is a quick code snippet to calculate the Mode:
public static double calculateMode(final double[] numberList) {
double[] cnts = new double[numberList.length];
double mode = 0, max = 0;
for (int i = 0; i < numberList.length; i++) {
/* Update Count Counter */
cnts[numberList[i]]++;
/* Check */
if (max < cnts[numberList[i]]) {
/* Update Max */
max = cnts[numberList[i]];
/* Update Mode */
mode = numberList[i];
}
}
/* Return Result */
return mode;
}
try sorting the element into an array.it will give following results:
[49,53,60,71,75,92]
suppose you stored it in array A.
int arrLength=A.length();
for(i=0,sum=0;i<arrlength;i++)
sum=sum+A[i]
mean=sum/arrLength;
median=A[arrLength/2]
I think you didn't sort the elements before finding median.
Do same thing to calculate range.It will be easier , I feel

Finding the median and max value of an array in java

I used this code to calculate the max value and the median element in an array of integers, but when I call the methods in my client class, both of these two methods produce an output of zero. The name of the array is "grades" and it is made of randomly generated integers
import java.util.*;
public class StudentGrades {
private int [] grades;
//Constructor
public StudentGrades ( int students)
{
Random number = new Random();
grades = new int[students];
for (int i = 0 ; i < students ; i++)
{
grades[i] = number.nextInt(99) + 1;
}
}
double median;
public void median()
{
Arrays.sort(grades) ;
double median ;
if (grades.length % 2 == 0)
{
int indexA = (grades.length - 1 ) /2;
int indexB = (grades.length)/2;
median = ((double) (grades[indexA] + grades[indexB]))/2;
}
else
{
int medIndex = (grades.length-1) / 2;
median = grades[ medIndex ];
}
}
public double getMedian()
{
return median;
}
int max;
public int getHighest()
{
for(int i = 0 ; i < grades.length - 1 ; i++)
{
int max = 0;
if(grades[i] > max)
{
max = grades[i];
}
}
return max;
}
In my driver, I simply had to prove that the method worked correctly, so it's:
System.out.println(" The highest grade is" + grades.getHighest());
System.out.println("The median grade is" + grades.getMedian());
Few mistakes.
1.) Might be calling getMedian(), whereas the logic is inside median() method.
2.) Inside method, getHighest(),
a.) No need to loop the array, since array is already sorted. So i have commented the code.
Just get the value at last index of array.
public class Test {
static int max;
static double median;
static int[] grades = { 2, 3, 4, 5, 62, 34 };
public static void main(String args[]) {
Arrays.sort(grades);
median();
getHighest();
System.out.println(median);
System.out.println(max);
}
public static void median() {
if (grades.length % 2 == 0) {
int indexA = (grades.length - 1) / 2;
int indexB = (grades.length) / 2;
median = ((double) (grades[indexA] + grades[indexB])) / 2;
} else {
int medIndex = (grades.length - 1) / 2;
median = grades[medIndex];
}
}
public double getMedian() {
return median;
}
public static int getHighest() {
/* for (int i = 0 ; i < grades.length ; i++) {
if (grades[i] > max) {
max = grades[i];
}
}*/
max = grades[grades.length - 1];
return max;
}
Output
4.5
62

Return the amount of numbers below average

I am trying to write a program that returns the amount of numbers less than the average
For example, if I have the numbers 2, 3 and 4, the average would be (2.1+3.6+4.2)/3 = 3.3 and since 2.3 is below average it would return 1 as there is one number below the average.
I am getting an error that says
Type mismatch: cannot convert from double[] to int
My code:
public static void main(String[] args) {
double[] numbers = {2.1, 3.6, 4.2};
System.out.println(belowaverage(numbers));
}
public static int belowaverage(double[] ba) {
double sum = 0;
double average = 0;
for(int i = 0;i<ba.length;i++){
sum = sum + ba[i];
average = sum / ba.length;
if(ba[i]<average){
return ba;
}
}
You're trying to return the array ba which is the array holding your input data instead of the count.
You need to leave the computation of the average in your current for loop and then create a second for loop and an int count variable which you will increment each time you find a number in the ba array that is smaller than the average. Then outside of that loop you return count.
Also this line:
average = sum / ba.length;
Has to be outside of the first loop.
#Edit: others provided some code but it had either logical or compile time errors (not all of them I guess, the ones I checked) so here's a working version:
public static int belowaverage(double[] ba) {
double sum = 0;
double average = 0;
int count = 0;
for(int i = 0; i < ba.length; i++) {
sum = sum + ba[i];
}
average = sum / ba.length;
for(int i = 0; i < ba.length; i++){
if (ba[i] < average) {
count++;
}
}
return count;
}
You don't need to cast length to double as sum is of type double so the result will be promoted to the bigger type.
public static void main(String[] args) {
double[] numbers = {2.1, 3.6, 4.2};
System.out.println(belowaverage(numbers));
}
public static int belowaverage(double[] ba) {
double sum = 0;
int length = ba.length;
for (int i = 0; i < length; i++) {
sum += ba[i];
}
double average = sum / length;
int belowAvgCount = 0;
for (int i = 0; i < length; i++) {
if (ba[i] < average) {
belowAvgCount++;
}
}
return belowAvgCount;
}
This isn't going to work using only a single for loop, because you can't possibly compare anything to the average until you've calculated it.
Try separating your calculation of the average and the counting of terms below the average into two different loops:
public static int belowaverage(double[] ba) {
double sum = 0;
double average = 0;
for(double b : ba){
sum += b;
}
average = sum / ba.length;
int count = 0;
for(double b : ba){
if(b < average){
count++;
}
}
return count;
}
You need to work out the sum first, then compute the average and then count how many below this threshold.
try
public static int belowaverage(double[] ba) {
double sum = 0;
double average = 0;
int count = 0;
for(int i = 0;i<ba.length;i++){
sum = sum + ba[i];
}
average = sum / ba.length;
for(int i = 0;i<ba.length;i++){
if (ba[i] < average) count++;
}
return count;
}

Categories

Resources