Freitag, 1. Januar 2010

prime numbers

Class to write prime numbers into a file.
Suggestions how to optimize the code are welcome.

package at.ande.primenumbers;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;

public class primenumbers {

 public static void main(String[] args) throws IOException {
  int i = 3;
  boolean newMark = false;
  File output;
  if (!((output = new File("output.txt")).exists())) {
   output.createNewFile();
  }
  LineNumberReader lineReader = new LineNumberReader(new FileReader(output));
  int lineNumbers = 0;
  String sLast = null;
  while ((sLast = lineReader.readLine()) != null) {
   lineNumbers++;
   if (lineReader.getLineNumber() == 1) {
    lineReader.mark(65365);
   }
   i = Integer.parseInt(sLast);
  }
  FileWriter fw = new FileWriter("output.txt", true);
  if (lineNumbers == 0) {
   fw.write("3\n");
   fw.flush();
   lineReader.mark(65535);
  }
  while (true) {
   try {
    lineReader.reset();
   } catch (Exception e) {
    lineReader = new LineNumberReader(new FileReader(output));
    newMark = true;
   }
   i = i + 2;
   while (true) {
    String sPrime = lineReader.readLine();
    if (newMark && lineReader.getLineNumber() == 1) {
     lineReader.mark(65365);
     newMark = false;
    }
    int prime = 0;
    if (sPrime != null) {
     prime = Integer.parseInt(sPrime);
    }
    if (sPrime == null || i < (prime * prime)) {
     fw.write(i + "\n");
     fw.flush();
     break;
    }
    if (i % prime == 0) {
     break;
    }
   }
  }
 }
}



update2: catchblock for .insert()

6 Kommentare:

  1. my algorithm when I read config file only at first run of the program:

    public constructor(){

    synchronized(INIT_FLAG){ init(); }

    }

    private init(){

    if(parameters.get(INIT_FLAG) != null) { return; }

    //here comes to to execute only one time

    }

    you can adapt that code for your issue to re-read the file but not to re-instance the class.

    AntwortenLöschen
  2. muss natürlich "private void init()" heißen ;-)

    AntwortenLöschen
  3. Solution 1:
    Den Stream nicht closen, sondern resetten :)

    lineReader = new LineNumberReader(new FileReader(output));
    lineReader.mark(65535);
    while (true) {
    lineReader.reset();
    i = i + 2;
    while (true) {
    String sPrime = lineReader.readLine();
    int prime = 0;
    if (sPrime != null) {
    prime = Integer.parseInt(sPrime);
    }
    if (sPrime == null || i < (prime * prime)) {
    fw.write(i + "\n");
    fw.flush();
    break;
    }
    if (i % prime == 0) {
    break;
    }
    }

    AntwortenLöschen
  4. Solution 2, weil das ParseInt verbraucht höllisch viel Zeit.... ....alles binär rausschreiben....

    public static void main(String[] args) throws IOException {
    int i = 3;
    RandomAccessFile data = new RandomAccessFile("output.txt", "rw");
    long totalLength = data.length();
    if (totalLength > 0) {
    data.seek(totalLength-4);
    i = data.readInt();
    } else {
    data.writeInt(i);
    }

    while (true) {
    i = i+2;
    data.seek(0);
    while (true) {
    int prime = data.readInt();
    if (i < (prime * prime)) {
    data.seek(data.length());
    data.writeInt(i);
    break;
    }
    if (i % prime == 0) {
    break;
    }
    }
    }
    }

    AntwortenLöschen
  5. Both solutions from Harry works fine, but first has a great performance advance.
    To get the prime number 1054369 the first one needs 2260 ms, the second 25844 ms.

    AntwortenLöschen
  6. The reason why binary access is so slow, is that there are much more syscalls and there is no optimization like in the Reader and InputStream implementations.

    However, there is a simple speedup possible in integrating a small buffer into the binary reader, like this:

    public class Main {

    private static final int BUFFERSIZE = 4096;

    private static byte[] data = new byte[BUFFERSIZE*4];
    private static int[] nextInts = new int[BUFFERSIZE];
    private static int currentPos = -1;
    private static int maxPos = 0;

    /**
    * @param args the command line arguments
    */
    public static void main(String[] args) throws IOException {
    int i = 3;
    RandomAccessFile write = new RandomAccessFile("output.txt", "rw");
    RandomAccessFile read = new RandomAccessFile("output.txt", "r");
    long totalLength = write.length();
    if (totalLength > 0) {
    write.seek(totalLength-4);
    i = write.readInt();
    } else {
    write.writeInt(i);
    }
    Long start = System.currentTimeMillis();
    while (true) {
    i = i+2;
    read.seek(0);
    currentPos = -1;
    while (true) {
    int prime = getNextPrime(read);
    if (i < (prime * prime)) {
    write.seek(write.length());
    write.writeInt(i);
    break;
    }
    if (i % prime == 0) {
    break;
    }
    }
    if (i > 100000) break;
    }
    Long ende = System.currentTimeMillis();
    String text = Long.toString(ende-start);
    System.out.println("Dauer: "+text);
    }

    private static int getNextPrime(RandomAccessFile file) throws IOException {
    if (currentPos == -1) {
    maxPos = file.read(data, 0, BUFFERSIZE*4);
    if ((maxPos > -1) && (maxPos % 4 == 0)) {
    currentPos = 0;
    } else {
    return file.readInt();
    }
    }

    int result = byteArrayToInt(data, currentPos*4);
    if (++currentPos >= maxPos) currentPos = -1;
    return result;
    }

    public static int byteArrayToInt(byte[] b, int offset) {
    int value = 0;
    for (int i = 0; i < 4; i++) {
    int shift = (4 - 1 - i) * 8;
    value += (b[i + offset] & 0x000000FF) << shift;
    }
    return value;
    }


    }

    AntwortenLöschen