2

我正在逐字节读取四个文件并比较所有四个字节以从这四个字节中生成一个最终字节。它的工作方式是:

  1. 如果所有字节都是0,则输出0
  2. 如果除了 1 个字节之外的所有字节都是0,则输出奇数字节输出(如果字节是0, 0, 1, 0,那么我将输出 a 1
  3. 如果 2 个字节是0,那么我随机输出一个非0字节
  4. 如果 1 个字节是0,则我从其他 3 个字节中输出出现次数最多的字节,否则在平局的情况下,我从该集合中输出一个随机字节
  5. 如果所有字节都不是0,那么我输出出现次数最多的字节,否则在平局的情况下,我从该集合中输出一个随机字节

需要注意的重要一点是,“随机”并不一定是随机的,我可以选择最方便的一个。

所以我对此进行了一些思考,但我仍然无法想出从这些数字中获得输出的绝对最快的方法。我注意到的一件事是,如果我读取的前两个字节相同且非零,那么我可以跳过接下来的两个字节并只输出前两个字节中的一个。如果前三个字节是0,那么我可以输出最后一个字节。我还可以用第一个字节和第二个字节检查第三个字节,看看它们是否相等,这样我就可以避免进入第 4 个字节,但我需要它尽可能高效。我需要运行这个算法大约 80 亿次,所以每一点都很重要 =)

所以无论如何,最有效的方法是什么?(伪代码?或其他)

这就是程序的样子(至少是它的外壳):

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

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

      FileInputStream in1 = null;
      FileInputStream in2 = null;
      FileInputStream in3 = null;
      FileInputStream in4 = null;
      FileOutputStream out = null;  

      try {
         in1 = new FileInputStream("1.dd");
         in2 = new FileInputStream("2.dd");
         in3 = new FileInputStream("3.dd");
         in4 = new FileInputStream("4.dd");
         BufferedInputStream in1b = new BufferedInputStream(in1);
         BufferedInputStream in2b = new BufferedInputStream(in2);
         BufferedInputStream in3b = new BufferedInputStream(in3);
         BufferedInputStream in4b = new BufferedInputStream(in4);
         out = new FileOutputStream("final.dd");
         int a;
         int b;
         int c;
         int d;
         int o; 

         while ((a = in1.read()) != -1) {
            b = in2.read();
            if (a == b && a != 0)
               o = a;
            else {
               c = in3.read();
               d = in4.read();
            }
            System.out.println((byte) c);
            out.write((byte) o);
         }
      } finally {
         if (in1 != null) {
            in1.close();
            in2.close();
            in3.close();
            in4.close();
         }
         if (out != null) {
            out.close();
         }
      }
   }
}

编辑:80亿,不是800万

EDIT2:正如评论中所指出的,由于同步,我不能跳过阅读字符。

4

2 回答 2

1

这个 while 循环不起作用:

while ((a = in1.read()) != -1) {
    b = in2.read();
    if (a == b && a != 0)
        o = a;
    else {
        c = in3.read();
        d = in4.read();
    }
    System.out.println((byte) c);
    out.write((byte) o);
}

因为有时您会读取 file1 和 file2,有时您会读取所有四个文件。

另一点:当您读取所有四个文件时o,未设置或具有前一轮的值。c如果您只读取 file1 和 file2,这也适用于。所以,为了解决这个问题,你总是必须阅读所有四个文件,然后你的循环的性能就没有那么重要了。

于 2012-10-28T21:08:23.440 回答
1

如果所有字节都为0,则输出0

输出 a+b+c+d。

如果除了 1 个字节之外的所有字节都是 0,则输出奇数字节输出(如果字节为 0,0,1,0,那么我将输出 1)

和上面一样。这已经为您节省了一个案例。如果任意三个字节为零,则输出总和。

如果 2 个字节为 0,则我随机输出一个非 0 字节如果 1 个字节为 0,则我从其他 3 个字节中输出出现次数最多的字节,否则在平局的情况下,我从该集合中输出一个随机字节如果所有字节都不为 0,则输出出现次数最多的字节,否则在平局的情况下,我从该集合中输出一个随机字节

这些案例其实都是一样的。输出出现次数最多的非零字节,或者在出现平局时输出随机字节。

所以实际上只有两种情况需要考虑:至少三个零字节,以及两个或更少。

事实上,所有的情况都是一样的。您可以将上述第二种解决方案应用于所有情况。完全不将它们分开可能会更快。

但首先在这些 FileInputStreams 周围添加了 BufferedInputStreams。

于 2012-10-28T20:59:08.837 回答