2016-04-12 3 views
-1

Wir versuchen derzeit, den Kmeans-Algorithmus in Java zu implementieren. Unser Problem ist das:Nach einer while-Schleife: Warum ist ein Array, das gerade leer geschrieben wurde?

Wir verwenden die getData() Methode, um ein zweidimensionales Array mit Daten aus einer Datei zu füllen. Innerhalb der While-Schleife in der getData() Methode haben wir eine println() und wir haben eine andere direkt vor dem Rückkehr-Befehl.

Die erste println() gibt uns die richtigen Werte, die wir gerade von der Datei erhalten haben.

Die zweite println() gibt uns nur 0.0 für jedes Feld in diesem Array, mit Ausnahme von arrayList[299][0].

Warum ist das?

class KMeans { 

    // Number of clusters 
    int numberOfClusters = 4; 
    // Starting point for each cluster (these values should be better than completely random values for our given data set) 
    static double[] a = new double[]{-1.5, 2.0}; 
    static double[] b = new double[]{-1.5, 7.0}; 
    static double[] c = new double[]{1.5, 7.0}; 
    static double[] d = new double[]{1.5, 2.0}; 
    static double[][] pointArray; 

    // This calculates the distance between a given point from the data set and a centroid 
    public static double calculateDistance(double[] point, double[] centroid) { 
     // get difference for X coordinates 
     double maxX = Math.max(point[0], centroid[0]); 
     double minX = Math.min(point[0], centroid[0]); 
     double differenceX = maxX - minX; 
     double differenceXSquared = Math.pow(differenceX, 2); 

     // get difference for Y coordinates 
     double maxY = Math.max(point[1], centroid[1]); 
     double minY = Math.min(point[1], centroid[1]); 
     double differenceY = maxY - minY; 
     double differenceYSquared = Math.pow(differenceY, 2); 

     // The whole thing is nothing other than pythagoras 
     double zSquared = differenceXSquared + differenceYSquared; 
     double z = Math.sqrt(zSquared); 
     return z; 
    } 

    // This calculates which of the given distances is the lowest 
    public static double[] nearestCluster(double e, double f, double g, double h) { 
     double x = Math.min(e, f); 
     double y = Math.min(x, g); 
     double z = Math.min(y, h); 

     if (z == e) { 
      return a; 
     } 
     if (z == f) { 
      return b; 
     } 
     if (z == g) { 
      return c; 
     } else { 
      return d; 
     } 
    } 

    // Read the file 
    public static double[][] getData() { 
     try (BufferedReader br = new BufferedReader(new FileReader("/home/john/Downloads/data.txt"))) { 
      String line; 
      int i = 1; 
      int j = 0; 
      while ((line = br.readLine()) != null) { 
       // Create the array in which we store each value 
       pointArray = new double[i][4]; 
       //Splits each line a the space and writes it to an array 
       String[] split = line.split("\\s+"); 

       // Cast the strings to double and write them to our pointArray   
       pointArray[j][0] = Double.parseDouble(split[0]); 
       pointArray[j][1] = Double.parseDouble(split[1]); 
       System.out.println(pointArray[0][0]); 
       i++; 
       j++; 
      } 
     } catch (IOException e) { 
     } 
     System.out.println(pointArray[0][0]);   
     return pointArray; 
    } 

    public static void main(String[] args) throws FileNotFoundException, IOException { 
     pointArray = getData(); 
     for (double[] x : pointArray) { 
      double distanceA = calculateDistance(x, a); 
      double distanceB = calculateDistance(x, b); 
      double distanceC = calculateDistance(x, c); 
      double distanceD = calculateDistance(x, d); 

      // Assigns the closest cluster to each point (not too efficent because we call the function twice, but it works) 
      x[2] = nearestCluster(distanceA, distanceB, distanceC, distanceD)[0]; 
      x[3] = nearestCluster(distanceA, distanceB, distanceC, distanceD)[1]; 
     } 
    } 
} 
+6

'pointArray = neue Doppel [i] [4];' - was versuchst du hier zu tun? Sie setzen die Array-Variable in jeder Iteration zurück. – Eran

+0

Die Idee ist, die Größe des Arrays abhängig von der Größe der Daten, die wir aus der Datei erhalten, dynamisch zu skalieren. – user2765654

+3

Das funktioniert nicht so. Besser eine Liste verwenden. – Fildor

Antwort

5

Die Linie

pointArray = new double[i][4]; 

reinitialisiert das Array jedes Mal durch die Schleife. Tatsächlich wirfst du jeden Wert außer der letzten Zeile weg, die du gelesen hast.

Verwenden Sie stattdessen eine ArrayList, um jede einzelne Linie zu halten. Stellen Sie sie vor dem while Schleife wie folgt aus:

List<Double[]> pointList = new ArrayList<>(); 

Dann sind Sie bei jeder Zeile wie diese hinzufügen können:

Double[] points = new Double[4]; 
// ... 
points[0] = Double.parseDouble(split[0]); 
// etc. 
pointList.add(points); 

dann entweder zurückgeben pointList oder konvertieren es für die Rückkehr in ein Array.

Verwandte Themen