Java - Finding the average of an array while excluding a particular value. - java

I am trying to calculate and return the average of an array of integer values. The problem is, the array I am calculating the average from has values I need to find the average of, and values I need to exclude.
For example, take this as being my data set in the array.
20, -999, -10, 50, -999, 40, 30
I need to find the average but exclude any -999 value from the calculation.
How can I go about removing the -999 value from my sums and then find the new value to divide by at the end? Is there a way to keep count of the values I exclude? How can I exclude a value and move on to the next?
public static double averageTemperature(int[] temperatures)
{
double sum = 0.0;
double avg = 0.0;
for (int i =0; i < temperatures.length; i++)
{
if (i == -999)
{
// what technique is there to exlude and keep counting?
}
else
{
sum += i;
}
}
avg = sum / temperatures.length;
return avg;
}

This should be pretty straightforward - just use a variable as counter for the "valid" entries. You also need to access the values in the array properly. Here's a proposal (untested), which assumes "valid" entries are those not equal t0 -999 (modify the condition as you like):
public static double averageTemperature(int[] temperatures)
{
double sum = 0.0;
double avg = 0.0;
int validEntries = 0;
for (int i =0; i < temperatures.length; i++)
{
// process only "valid" entries
if (temperatures[i] != -999)
{
sum += temperatures[i];
++validEntries;
}
}
avg = sum / validEntries;
return avg;
}

Using Java 8 you can do;
temperatures = Arrays.stream(temperatures).filter(x -> x != -999).toArray();
You can exclude any array value this way using predicate statements.
Calculating the mean is as simple as just looping the array and dividing by the length then.
float mean;
for (int i = 0; i < temperatures.length; ++i) {
mean += (float) temperatures[i];
}
mean /= (float) temperatures.length;
Note to use a float for the mean and cast your integer array values to float also to avoid integer division, as well as the length of the array.

suppose you are correct with the logic but you are not getting the sum of the temperature values.
public static double averageTemperature(int[] temperatures)
{
double sum = 0.0;
double avg = 0.0;
for (int i =0; i < temperatures.length; i++)
{
if (temperatures[i] == -999)
{
continue;
}
else
{
sum += temperatures[i];
}
}
avg = sum / temperatures.length;
return avg;
}
hope this is what you are looking for.

The easiest way to compute the average while filtering out any unwanted values would be:
double average = Arrays.stream(temperatures)
.filter(i -> i != -999)
.average();

Related

How to calculate average of an array for only entered values

I'm trying to calculate the average of an array for only the values that aren't 0. My array is of size 15, because it could have up to 15 values in it.
When I calculate the average, it uses all 15 values, even though 12 of them are 0 at the start. How do I prevent 0.0’s from being considered?
for(double element: majorA) {
Sum += element;
}
average = sum / majorA.length;
System.out.printf("%.5f\n", average);
The array also isn't a defined set, but dependent on what the user inputs. The initial array is:
double[] majorA = new double[15];
Then gets values as need:
majorA[0] = num1;
majorA[1] = num2;
...
I would just add a counter that keeps track and use that instead of the array length.
int count = 0;
for(double element: majorA) {
if(element > 0.0) {
Sum += element;
count += 1;
}
}
average = sum / count;
System.out.printf("%.5f\n", average);
You can do it in one line with
Arrays.stream(majorA).filter(d -> d != 0).average().orElse(0)
this will filter out all values that are 0s and will calculate the average. Even if there is nothing left in the array will display 0 because of .orElse(0)
you can use a counter in the loop that increments only if the number !=0
int count = 0;
for(double element: majorA) {
if(element != 0.0){
sum += element;
count++;
}
}
average = (count == 0) ? 0 : sum / count;

While loops being ignored

I'm trying to write a simple program which will take a number of inputs from the user and produce the max number (Highest number) min number (Lowest Number) and the average.
So far I have written the code but found that the second and third while loops were being ignored. I tested this by outputting println's. I'm new to Java but any help is appreciated :)
public void analyseInput() {
UI.clearText();
UI.print("input (end with 'done')");
double sum = 0;
double i=0;
for( i=0; UI.hasNextDouble(); i++){ //average
double amt = UI.nextDouble();
sum = (sum + amt);
}
UI.println("test0");
int maxAge = 0;
while(UI.hasNextDouble()){ //max
int age = UI.nextInt();
while(age>maxAge){
maxAge = age;
UI.println(maxAge);
}
}
double minAge = 0;
while(UI.hasNextDouble()){ //min
double age = UI.nextDouble();
if(age<minAge){
minAge = age;
}
}
double average = sum/i;
UI.nextLine(); // to clear out the input
UI.println(average);
UI.println(minAge);
}
Take out your for loop.
using it empties ui.doubles.
furthermore instead of iterating through your stack twice you might as well do the max, min and average calculations in one loop. also your max and finder isn't right, because it would only work on a sorted list and if the list was already sorted you would just look at either end of it.
If you need the min age, max age, average for a set of data, instead of parsing over it a bunch of time, you can simply do it in one go.
public void analyseInput() {
UI.clearText();
UI.print("input (end with 'done')");
double sum = 0;
double i=0;
double maxAge = Double.MIN_VALUE, minAge = Double.MAX_VALUE;
for( i=0; UI.hasNextDouble(); i++){ //average
double amt = UI.nextDouble();
sum = (sum + amt);
maxAge = Math.max(amt, maxAge);
minAge = Math.min(amt, minAge);
}
double average = sum/i;
UI.nextLine(); // to clear out the input
UI.println(average);
UI.println(minAge);
}
You must to do all operations (max, min, avg) inside a single while-loop and initialize your variable right. To each new double value, update the min and max variable. Add to an accumulator all the values and calculate the average after the loop.

Java - finding the variance - would this work?

Link to exercise: mooc.cs.helsinki.fi/programming-part1/material-2013/week-3?noredirect=1#e67
Would this work? I feel like my math is correct, but I can't test my code because I'm at work.
SUM:
int a = 0;
int sum = 0;
while (a < list.size()) {
sum += list.get(a);
a++;
}
return sum;
AVERAGE:
double average = sum(list)/list.size();
return average;
VARIANCE:
int a = 0;
double b = list.get(a) - average(list);
double sum = 0;
while (a < list.size()) {
sum += Math.pow(b, 2);
a++;
}
double variance = sum / (list.size() - 1);
return variance;
Would that work?
FOLLOW UP QUESTION:
This is apparently the "correct" way to do it...
double sumDiffSquared = 0.0;
double avg = average(list);
for (int value : list) {
double difference = value - avg;
difference *= difference;
sumDiffSquared += difference;
double variance = difference / (list.size() - 1);
}
return variance;
Okay so I THINK I understand most of it (notes below)...
double difference = value - avg;
Everything from "list" was put into the variable "value" and now we are subtracting the previously calculated average from each number within the variable "value" one-by-one and putting the new values into the variable "difference". Makes perfect sense.
difference *= difference;
We are now multiplying each number within the variable "difference" by itself. Once again, one-by-one. Makes sense.
Here's where I get lost...
sumDiffSquared += difference
This is what makes no sense to me. Why/how does this add the values together? To me it looks like the value of the variable "sumDiffSquared" is 0, so this would just be adding 0 to each of the values in the variable "difference"...
The variable sumDiffSquared does not get reset for each loop, therefore it is accumulating the value of difference for each loop.

Quadratic Time for 4-sum Implementation

Given an array with x elements, I must find four numbers that, when summed, equal zero. I also need to determine how many such sums exist.
So the cubic time involves three nested iterators, so we just have to look up the last number (with binary search).
Instead by using the cartesian product (same array for X and Y) we can store all pairs and their sum in a secondary array. So for each sum d we just have to look for -d.
This should look something like for (close to) quadratic time:
public static int quad(Double[] S) {
ArrayList<Double> pairs = new ArrayList<>(S.length * S.length);
int count = 0;
for (Double d : S) {
for (Double di : S) {
pairs.add(d + di);
}
}
Collections.sort(pairs);
for (Double d : pairs) {
int index = Collections.binarySearch(pairs, -d);
if (index > 0) count++; // -d was found so increment
}
return count;
}
With x being 353 (for our specific array input), the solution should be 528 but instead I only find 257 using this solution. For our cubic time we are able to find all 528 4-sums
public static int count(Double[] a) {
Arrays.sort(a);
int N = a.length;
int count = 0;
for(int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
int l = Arrays.binarySearch(a, -(a[i] + a[j] + a[k]));
if (l > 0) count++;
}
}
}
return count;
}
Is the precision of double lost by any chance?
EDIT: Using BigDecimal instead of double was discussed, but we were afraid it would have an impact on performance. We are only dealing with 353 elements in our array, so would this mean anything to us?
EDITEDIT: I apologize if I use BigDecimal incorrectly. I have never dealt with the library before. So after multiple suggestions I tried using BigDecimal instead
public static int quad(Double[] S) {
ArrayList<BigDecimal> pairs = new ArrayList<>(S.length * S.length);
int count = 0;
for (Double d : S) {
for (Double di : S) {
pairs.add(new BigDecimal(d + di));
}
}
Collections.sort(pairs);
for (BigDecimal d : pairs) {
int index = Collections.binarySearch(pairs, d.negate());
if (index >= 0) count++;
}
return count;
}
So instead of 257 it was able to find 261 solutions. This might indicate there is a problem double and I am in fact losing precision. However 261 is far away from 528, but I am unable to locate the cause.
LASTEDIT: So I believe this is horrible and ugly code, but it seems to be working none the less. We had already experimented with while but with BigDecimal we are now able to get all 528 matches.
I am not sure if it's close enough to quadratic time or not, time will tell.
I present you the monster:
public static int quad(Double[] S) {
ArrayList<BigDecimal> pairs = new ArrayList<>(S.length * S.length);
int count = 0;
for (Double d : S) {
for (Double di : S) {
pairs.add(new BigDecimal(d + di));
}
}
Collections.sort(pairs);
for (BigDecimal d : pairs) {
BigDecimal negation = d.negate();
int index = Collections.binarySearch(pairs, negation);
while (index >= 0 && negation.equals(pairs.get(index))) {
index--;
}
index++;
while (index >= 0 && negation.equals(pairs.get(index))) {
count++;
index++;
}
}
return count;
}
You should use the BigDecimal class instead of double here, since exact precision of the floating point numbers in your array adding up to 0 is a must for your solution. If one of your decimal values was .1, you're in trouble. That binary fraction cannot be precisely represented with a double. Take the following code as an example:
double counter = 0.0;
while (counter != 1.0)
{
System.out.println("Counter = " + counter);
counter = counter + 0.1;
}
You would expect this to execute 10 times, but it is an infinite loop since counter will never be precisely 1.0.
Example output:
Counter = 0.0
Counter = 0.1
Counter = 0.2
Counter = 0.30000000000000004
Counter = 0.4
Counter = 0.5
Counter = 0.6
Counter = 0.7
Counter = 0.7999999999999999
Counter = 0.8999999999999999
Counter = 0.9999999999999999
Counter = 1.0999999999999999
Counter = 1.2
Counter = 1.3
Counter = 1.4000000000000001
Counter = 1.5000000000000002
Counter = 1.6000000000000003
When you search for either pairs or an individual element, you need to count with multiplicity. I.e., if you find element -d in your array of either singletons or pairs, then you need to increase the count by the number of matches that are found, not just increase by 1. This is probably why you're not getting the full number of results when you search over pairs. And it could mean that the number 528 of matches is not the true full number when you are searching over singletons. And in general, you should not use double precision arithmetic for exact arithmetic; use an arbitrary precision rational number package instead.

How to write 1+1/2+1/3....+1/4999+1/5000 in java?

How to write 1+1/2+1/3....+1/4999+1/5000 in java?
I have tried this but didnt work.
public class Harmonic{
public static void main(String[] args){
double sum = 0;
for(int i=1; i<=5000; i++){
sum+=1/i;
}
System.out.println(sum);
}
}
Adding numbers from smallest to largest will have a lower rounding error. If you compare the result with higher precision, you can see smaller to larger is closer.
double sum = 0;
for (int i = 1; i <= 5000; i++) {
sum += 1.0 / i;
}
System.out.println("From largest to smallest " + sum);
double sum2 = 0;
for (int i = 5000; i >= 1; i--) {
sum2 += 1.0 / i;
}
System.out.println("From smallest to largest " + sum2);
BigDecimal sum3 = BigDecimal.ZERO;
for (int i = 5000; i >= 1; i--) {
sum3 = sum3.add(BigDecimal.ONE.divide(BigDecimal.valueOf(i), 30, BigDecimal.ROUND_HALF_UP));
}
System.out.println("BigDecimal " + sum3);
prints
From largest to smallest 9.094508852984404
From smallest to largest 9.09450885298443
BigDecimal 9.094508852984436967261245533401
1 is an int constant, so 1 / (any int bigger than 1) is 0. You need to specify that you want a floating point division, by using 1.0 (float):
sum+=1.0/i;
^
That's a homework, then I just help you with a tip: be careful of variable types. 1/10 is equal to 0 if we consider it as an integer.
Try this instead:
sum += 1.0 / i;
How about:
public class Harmonic{
public static void main(String[] args){
double sum = 0;
for(int i=1; i<=5000; i++){
sum+=1.0/(double)i;
}
System.out.println(sum);
}
}
After the first iteration 1/i will always be 0 since it's done in integer arithmetic. Therefore you're final answer will just be 1. Change it to 1.0/i to get double arithmetic, and keep in mind that when you're loop finishes you may have a fair amount of error due to precision loss while using doubles. You can try it out and see how accurate it is though.
because i is an int so the division will be truncated... try putting sum+ = 1/(double)i
java-8 solution for calculating Harmonic sum:
public static double harmonicSum(int n) {
return IntStream.rangeClosed(1, n)
.mapToDouble(i -> (double) 1 / i)
.sum();
}

Categories