0

这是一个很长的。

我有一个非常奇怪的问题。我需要从文本文件中读取两个矩阵,将它们相乘,然后打印出结果。这一切都很容易。问题是包含矩阵的文件如下所示:

1 2 1 2 3
3 4 4 5 6
5 6
7 8

这个疯狂的东西是如何工作的(仅供参考,可以跳过这部分):

  1. 阅读第一栏。一旦你点击空格或文件的末尾,你就有了 FIRST 矩阵中的行数。

  2. 逐行计算每行的整数个数。一旦该计数下降,您就会知道第二个矩阵有多少行。如果第一个矩阵比文件“短”,那么这一步是不必要的,因为第二个只是文件中的行数。

  3. 由于乘法要求矩阵一的列数与矩阵二的行数相同([3x6 * 6x4] 有效,[3x6 * 5x4] 无效),因此通过知道矩阵一中的列数,我们可以找到行数在矩阵二中,反之亦然。

我需要找到任何一个值。

因此,从该文件矩阵中,一个将是

1 2
3 4
5 6
7 8

二是

1 2 3
4 5 6

所以你会认为你可以只计算第一列中的行数和最后一行中的列数来查找所有内容,但有时文件看起来像这样:

1 2 1 2 3
3 4 4 5 6
      7 8

所以我只需要根据左下角是 int 还是 whitespace 进行一些条件处理。我正在考虑将整个文件读入二维数组并从那里进行操作。

所以这是我的正式问题:

我需要单独读取文件的每个字符,无论是 int 还是空格,所以我可以构建一个忠实的 Array[][]。这样做的最佳方法是什么?我尝试过 Scanner、StringTokenizer、FileInputStream、BufferedInputStream、Reader 和 FileReader,但它们都没有给我一个简单的 char by char。

其次,关于将矩阵从统一的 Array[][] 拆分为两个较小的 Array[][] 有什么建议吗?

4

4 回答 4

0

看来,对于两个矩阵,最大行数是行数,最大列数是行长 + 1 / 2,不包括用于行尾的任何内容(例如 CRLF)

当您扫描文件以获取这两位信息时,如果第一个字符扫描时都没有跳过,则还要查找第一个或最后一个字符是否为空格,直到碰到第二个数组(如果最后一个是),则向后扫描直到碰到进入第一个其他可能性当然是两个具有相同维度的数组。

有了这些信息,您可以创建两个数组,然后再次扫描文件并将值插入适当的位置。

这有点残酷,但它会起作用并且易于测试。

于 2012-11-14T22:20:45.770 回答
0

我建议将问题分为 4 个阶段:阅读文本、构建字符串单元格数组、构建整数矩阵数组、做矩阵的乘积:

import java.util.ArrayList;
import java.util.List;

public class MatrixMul {
   static String[][] text2StrMatrices( String[] text ) {
      List< String[] > w = new ArrayList<>( 12 );
      for( String line : text )
      {
         List< String > l = new ArrayList<>( line.length() / 2 );
         for( int i = 0; i < line.length(); ++i )
         {
            char c = line.charAt( i );
            if( c == ' ' )
            {
               l.add( " " );
               ++i;
            }
            else {
               String num = "";
               while( c != ' ' && i < line.length()) {
                  num += c;
                  if( ++i < line.length()) {
                     c = line.charAt( i );
                  }
               }
               l.add( num );
            }
         }
         w.add( l.toArray( new String[l.size()]));
      }
      return w.toArray( new String[w.size()][] );
   }

   static int countValues( String[] row )
   {
      int count = 0;
      for( String value : row ) {
         if( value.trim().length() > 0 ) {
            ++count;
         }
      }
      return count;
   }

   static int[][][] strMatrices2IntegerMatrices( String[][] str ) {
      int count = str[0].length;
      int row = 0;
      while( row < str.length && count == countValues( str[row] )) {
         ++row;
      }
      int first = -1;
      for( int i = 0; first == -1 && i < str[row].length; ++i ) {
         if( str[row][i].trim().length() > 0 ) {
            first = i;
         }
      }
      int columns = 0;
      if( first > 0 ) {
         columns = first;
      }
      else {
         columns = countValues( str[row] );
      }
      List<int[]> w = new ArrayList<>(4);
      for( int r = 0; r < ( first == 0 ? str.length : row ); ++r )
      {
         int[] aRow = new int[columns];
         for( int c = 0; c < columns; ++c ) {
            aRow[c] = Integer.parseInt( str[r][c] );
         }
         w.add( aRow );
      }
      int[][][] result = new int[2][][];
      result[0] = w.toArray( new int[w.size()][] );
      w.clear();
      for( int r = 0; r < ( first == 0 ? row : str.length ); ++r )
      {
         int[] aRow = new int[str[0].length-columns];
         for( int c = columns; c < str[r].length; ++c ) {
            aRow[c-columns] = Integer.parseInt( str[r][c] );
         }
         w.add( aRow );
      }
      result[1] = w.toArray( new int[w.size()][] );
      return result;
   }

   private static int[][] matricesProduct( int[][] a, int[][] b )
   {
      int m = a.length;
      int n = b[0].length;
      int p = b.length;
      assert ( m == n ) || ( a[0].length == p ): "Incompatible dimensions";
      int[][] prod = null;
      if( p > -1 ) {
         prod = new int[m][n];
         for( int i = 0; i < m; ++i ) {
            for( int j = 0; j < n; ++j ) {
               for( int k = 0; k < p; ++k ) {
                  prod[i][j] += a[i][k] * b[k][j];
               }
            }
         }
      }
      return prod;
   }

   static void test(
      String     title,
      String[]   text,
      String[][] expectedStrMatrices,
      int[][][]  expectedMatrices,
      int[][]    expectedProduct )
   {
      System.out.println( title );
      final String[][] observedStrMatrices = text2StrMatrices( text );
      assert compare( expectedStrMatrices, observedStrMatrices ):
         "text2StrMatrices() failed";
      final int[][][] observedMatrices =
         strMatrices2IntegerMatrices( observedStrMatrices );
      assert compare( expectedMatrices, observedMatrices ):
         "strMatrices2IntegerMatrices() failed";
      final int[][] observedProduct =
         matricesProduct( observedMatrices[0], observedMatrices[1] );
      displayMatrix( observedProduct );
      assert compare( expectedProduct, observedProduct ):
         "matricesProduct() failed";
   }

   public static void main( String[] args ) {
      final String[] text1 = {
         "1 2 1 2 3",
         "3 4 4 5 6",
         "5 6",
         "7 8",
      };
      final String[][] expectedStrMatrices1 = {
         { "1", "2", "1", "2", "3" },
         { "3", "4", "4", "5", "6" },
         { "5", "6" },
         { "7", "8" },
      };
      final int[][][] expectedMatrices1 = {{
            { 1, 2 },
            { 3, 4 },
            { 5, 6 },
            { 7, 8 },
         },{
            { 1, 2, 3 },
            { 4, 5, 6 },
         }};
      final int[][] expectedProduct1 = {
         {  9, 12, 15 },
         { 19, 26, 33 },
         { 29, 40, 51 },
         { 39, 54, 69 },
      };
      test( "First test case", text1, expectedStrMatrices1, expectedMatrices1, expectedProduct1 );
      final String[] text2 = {
         "1 2 1 2 3",
         "3 4 4 5 6",
         "      7 8",
      };
      final String[][] expectedStrMatrices2 = {
         { "1", "2", "1", "2", "3" },
         { "3", "4", "4", "5", "6" },
         { " ", " ", " ", "7", "8" },
      };
      final int[][][] expectedMatrices2 = {{
            { 1, 2, 1 },
            { 3, 4, 4 },
         },{
            { 2, 3 },
            { 5, 6 },
            { 7, 8 },
         }};
      final int[][] expectedProduct2 = {
         { 19, 23 },
         { 54, 65 },
      };
      test( "Second test case", text2, expectedStrMatrices2, expectedMatrices2, expectedProduct2 );
   }// void main( String[] args )

   private static void displayMatrix( int[][] matrix ) {
      for( int i = 0; i < matrix.length; ++i ) {
         for( int j = 0; j < matrix[i].length; ++j ) {
            System.out.printf( "%2d ", matrix[i][j] );
         }
         System.out.println();
      }

   }

   static boolean compare( String[][] left, String[][] right ) {
      if( left.length != right.length ) {
         return false;
      }
      for( int i = 0; i < left.length; ++i ) {
         if( left[i].length != right[i].length ) {
            return false;
         }
         for( int j = 0; j < left[i].length; ++j ) {
            if( ! left[i][j].equals( right[i][j] )) {
               return false;
            }
         }
      }
      return true;
   }

   static boolean compare( int[][][] left, int[][][] right ) {
      if( left.length != right.length ) {
         return false;
      }
      for( int i = 0; i < left.length; ++i ) {
         if( left[i].length != right[i].length ) {
            return false;
         }
         for( int j = 0; j < left[i].length; ++j ) {
            if( left[i][j].length != right[i][j].length ) {
               return false;
            }
            for( int k = 0; k < left[i][j].length; ++k ) {
               if( left[i][j][k] != right[i][j][k] ) {
                  return false;
               }
            }
         }
      }
      return true;
   }

   private static boolean compare( int[][] left, int[][] right )
   {
      if( left.length != right.length ) {
         return false;
      }
      for( int i = 0; i < left.length; ++i ) {
         if( left[i].length != right[i].length ) {
            return false;
         }
         for( int j = 0; j < left[i].length; ++j ) {
            if( left[i][j] != right[i][j] ) {
               return false;
            }
         }
      }
      return true;
   }
}
于 2012-11-14T22:24:40.997 回答
0

文本文件只能逐行读取。因此读取一行,使用 String.split(" ") 将其拆分,并将结果数据填充到包含 Integer 链表的链表中。请记住,您必须跟踪拆分数据的位置在您的第二种情况下,在输入字符串中记住第二个矩阵的起始位置。

LinkedList<LinkedList<Integer>>

读取文件的所有行后,您拥有“最高”矩阵的完整行数,并且您可以将第一个矩阵的数据放入数组中,同时从链表中删除相同时间点的相同数据(Lisp 。流行音乐())。

  • 我无法想象一次运行就可以读取数组数组,因为您在读取文件时事先不知道行数。因此,您需要使用集合类。
  • 我建议使用 LinkedList,因为删除 wit pop 比使用由数组支持的集合非常有效且更快。
  • LinkedList 还可以在通过列表时有效地进行矩阵乘法。
于 2012-11-14T22:15:05.167 回答
0

您应该能够使用 FileInputStream 逐个字符地读取文件。

请注意,该read()方法在 EOF 处返回 -1。否则将返回值转换为字符。

于 2012-11-14T22:07:30.377 回答