2017-05-03 75 views
0

我想寫一個Java程序,它從文本文件讀取數據,並根據給定的問題計算一些不同的平均值。如何使用循環找到離平均值最遠的值?

我給出的文件包含了13張不同的十進制數(在文件的第一行表示)

我試圖找到:

  • 所有值的平均值。 (稱爲平均值A1。)
  • 所有值的平均值,不包括離A1最遠的值。 (稱此平均值爲A2。)
  • 所有值的平均值,不包括距離A2最遠的兩個值。 (將此平均值稱爲A3。)
  • 所有值的平均值,不包括距離A3最遠的三個值。
  • 。 。 。
  • 所有值的平均值,不包括距離A(N-1)最遠的N-1。 (這是一個元素的平均值;換句話說,該元素本身的值。)

這是我的代碼。我設法得到了A1,A2,A3和A4,但我不知道接下來要做什麼。 (我覺得我應該使用循環,但我不知道如何)

import java.io.File; 
import java.io.IOException; 
import java.util.Scanner; 

public class FurtherTweeking 
{ public static void main (String[] args) throws IOException { 

//Read the given file 
Scanner scan = new Scanner(new File("C:\\Users\\IdeaProjects\\src\\ArrayList.txt")); 
//The first line of the file gives the number of values that follow 
int Num = scan.nextInt(); 

//Reads the data into an array 
Double[] InputData = new Double[Num]; 
double ArraySum = 0; 
int i = 0; 
do { 
    InputData[i] = scan.nextDouble(); 
    i = i+1; 
} 
while(scan.hasNextLine()); 
scan.close(); 






//Calculate the sum of all input data 
for (int j = 0; j < Num; j++) { 
    if (InputData[j] != null) { 
     ArraySum = ArraySum + InputData[j]; 
    } 
} 
//Calculate the average of the original input data 
double A1 = ArraySum/(Num); 
System.out.println("A1: " + A1); 





//Scan through the array to find the value that is farthest (in either direction) from the average 
double Farthest = InputData[0]; 
for (int j = 0; j < Num; j++) { 
    if (InputData[j] != null) { 
     if (Math.abs (A1 - InputData[j]) > Math.abs (A1 - Farthest)) 
      Farthest = InputData[j]; 
    } 
} 
for (int u = 0; u < Num; u++){ 
    if (InputData[u] == Farthest){ 
     InputData[u] = null; 
    } 
} 
System.out.println("Most distant value: " + Farthest); 
//compute an average that does not include the most distant value. Print the new average. 
double A2 = (ArraySum - Farthest)/(Num - 1.0); 
System.out.println("A2: " + A2); 






double Farthest2 = InputData[0]; 
double Farthest3 = InputData[0]; 
for (int j = 0; j < Num; j++) { 
    if (InputData[j] != null) { 
     if (Math.abs (A2 - InputData[j]) > Math.abs (A2 - Farthest2)) { 
      Farthest3 = Farthest2; 
      Farthest2 = InputData[j]; 
     } 
     else if (Math.abs (A2 - InputData[j]) > Math.abs (A2 - Farthest3)) { 
      Farthest3 = InputData[j]; 
     } 
    } 
} 
System.out.println("Most distant value: " + Farthest2 + ", " + Farthest3); 
//compute an average that does not include the most distant value. Print the new average. 
double A3 = (ArraySum - Farthest - Farthest2 - Farthest3)/(Num - 3.0); 
System.out.println("A3: " + A3); 





double Farthest4 = InputData[0]; 
double Farthest5 = InputData[0]; 
double Farthest6 = InputData[0]; 
for (int j = 0; j < Num; j++) { 
    if (InputData[j] != null) { 
     if (Math.abs (A3 - InputData[j]) > Math.abs (A3 - Farthest4)) { 
      Farthest6 = Farthest5; 
      Farthest5 = Farthest4; 
      Farthest4 = InputData[j]; 
     } 
     else if (Math.abs (A3 - InputData[j]) > Math.abs (A3 - Farthest5)) { 
      Farthest6 = Farthest5; 
      Farthest5 = InputData[j]; 
     } 
     else if (Math.abs (A3 - InputData[j]) > Math.abs (A3 - Farthest6)) { 
      Farthest6 = InputData[j]; 
     } 
    } 
} 
System.out.println("Most distant value: " + Farthest4 + ", " + Farthest5+ ", " + Farthest6); 
//compute an average that does not include the most distant value. Print the new average. 
double A4 = (ArraySum - Farthest - Farthest2 - Farthest3 -Farthest4 - Farthest5 - Farthest6)/(Num - 6.0); 
System.out.println("A4: " + A4); 
} 
} 

感謝您的時間!

+0

注意,這個問題沒有得到很好的定義。在任何階段,如果最小值和最大值與平均值等距,那麼刪除哪個值?您的選擇將影響所有後續平均值。 –

回答

1

我會創建兩個UTIL功能:

/** Returns the average of a collection of double */ 
private static Double average(Collection<Double> coll) { 
    return coll.stream().collect(Collectors.averagingDouble(Double::doubleValue)); 
} 

/** Returns the first, most distant element of a collection from a defined value. */ 
private static Double furthest(Collection<Double> coll, Double value) { 
    return coll.stream() 
    .max((d1, d2) -> Double.compare(Math.abs(d1-value), Math.abs(d2-value))) 
    .orElse(null); 
} 

,並利用它們是這樣的:

Double[] array = new Double[]{1d,2d,3d,4d,5d,6d,7d,8d,9d}; 
List<Double> list = new ArrayList<>(Arrays.asList(array)); 

for (int i = 0; i < array.length; i++) { 

    double average = average(list); 
    System.out.printf("Average A%d: %.1f, List: %s\n", (i+1), average, input); 

    double furthest = furthest(list, average); 
    list.remove(furthest); 
} 

輸出:

Average A1: 5.0, List: [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] 
Average A2: 5.5, List: [2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] 
Average A3: 6.0, List: [3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] 
Average A4: 6.5, List: [4.0, 5.0, 6.0, 7.0, 8.0, 9.0] 
Average A5: 7.0, List: [5.0, 6.0, 7.0, 8.0, 9.0] 
Average A6: 7.5, List: [6.0, 7.0, 8.0, 9.0] 
Average A7: 8.0, List: [7.0, 8.0, 9.0] 
Average A8: 8.5, List: [8.0, 9.0] 
Average A9: 9.0, List: [9.0] 
+0

Double.compare()中的絕對差異? – DAle

+0

你是對的,謝謝。現在,第一個最遠的是由'furthest()' – Oneiros

+0

返回並且可能是因爲沒有獲得如此奇怪的輸出而選擇其他數字會更好? – DAle

0

我認爲你寫了一些更復雜的任務需要的東西(如果我正確理解你的任務)。想象一下,如果你沒有13個號碼,但即使是一千個號碼,那又怎樣?我給你寫了一些東西,可能並不完全是你需要的東西(但我不確定,可能是),但它會告訴你這個想法是如何完成的,我把代碼留在代碼中,所以你可以看到實際發生了什麼,我建議你運行這段代碼。

public static void main(String arg[]) { 
    List<Double> list = new ArrayList<>(Arrays.asList(3.2, 4.8, 5.2, 1.2, 9.8, 0.5, 6.6, 2.2, 7.1)); 

    while(list.size() > 0) { 
    System.out.println("Next iteration, list: " + list); 
    DoubleSummaryStatistics stats = list.stream().collect(DoubleSummaryStatistics::new, 
     DoubleSummaryStatistics::accept, DoubleSummaryStatistics::combine); 
    double average = stats.getAverage(); 
    double min = stats.getMin(); 
    double max = stats.getMax(); 
    double furthest = Math.abs(average - max) > Math.abs(average - min) ? max : min; 
    System.out.println("Average: " + average); 
    System.out.println("Minimum: " + min); 
    System.out.println("Maximum: " + max); 
    System.out.println("Furthest away: " + furthest); 
    list.remove(furthest); 
    } 
} 

我們在這裏做的是我們指望名單上的DoubleSummaryStatistics(它計算平均值,最大值,最小值等。對我們來說,看看鏈接),然後我們只是把我們需要的值。最遠的值可能是最大值或最小值,因此我們需要自己找到這個值。然後我們從列表中刪除該值並重新執行,直到列表中沒有元素。

+0

謝謝!但我不明白將數組更改爲列表的目的是什麼? (對不起,如果這是一個愚蠢的問題) –

+0

我只是喜歡在這個例子中使用列表,'ArrayList'在名稱暗示內部使用數組,但它包裝了很多有用的方法,並且隨着項目插入它變得更大還有很多其他的東西,比如'java Lists VS Arrays'或者類似的東西,你會發現很多:)在這個例子中我使用了list,因爲我們需要從它中刪除最遠的項目,不會那麼容易與陣列,其他更改將需要。 – Shadov

0

使用集合將是大名單慢,也許O(N * 2)。 相反,對於n個值的高效實現。將...

1. Put all values in a double[] array 
2. Sort array with Arrays.sort(double[n]). Time is o(n*log(n)) 
3. Calculate sum of array 
4. Setup markers a=0 and b=n-1 
5. Now each smaller average requires clipping at start or end of list, which corresponds to incrementing a or decrementing b 

利用上述算法的所有的平均值可以在O發現(N 的log(n))+ O(N)= O(Nlog(n))。速度更快,而且使用的內存也更少。

這裏是一個快速解決方案的代碼:

import java.util.Arrays; 

class Main { 

    public static void main(String[] args) { 
     double[] arD = {3.2, 4.8, 5.2, 1.2, 9.8, 0.5, 6.6, 2.2, 7.1}; 
     Arrays.sort(arD); 

     double sum = 0; 
     for (double d : arD) 
      sum += d; 

     int n = arD.length; 
     int a = 0, b = n - 1; 
     while (a <= b) { 
      int m = b - a + 1; 
      double avg = sum/m; 
      System.out.println("Average of range=[" + a + "," + b + "] is " + avg); 
      if (Math.abs(arD[a] - avg) > Math.abs(arD[b] - avg)) 
       sum -= arD[a++]; 
      else 
       sum -= arD[b--]; 
     } 

    } 
}